Compare commits
No commits in common. "a879360ebd281514867bf3f10c6e322cdedd0730" and "ce3c4b55f05080849bc03ddb5ddab29724e85f41" have entirely different histories.
a879360ebd
...
ce3c4b55f0
|
@ -26,12 +26,6 @@
|
||||||
### Improved
|
### Improved
|
||||||
* game overview: simplify playtime range display
|
* game overview: simplify playtime range display
|
||||||
* new session: order devices alphabetically
|
* new session: order devices alphabetically
|
||||||
* ignore English articles when sorting names
|
|
||||||
* added a new sort_name field that gets automatically created
|
|
||||||
* automatically fill certain values in forms:
|
|
||||||
* new game: name and sort name after typing
|
|
||||||
* new edition: name and sort name when selecting game
|
|
||||||
* new purchase: platform when selecting edition
|
|
||||||
|
|
||||||
## 1.3.0 / 2023-11-05 15:09+01:00
|
## 1.3.0 / 2023-11-05 15:09+01:00
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ custom_date_widget = forms.DateInput(attrs={"type": "date"})
|
||||||
custom_datetime_widget = forms.DateTimeInput(
|
custom_datetime_widget = forms.DateTimeInput(
|
||||||
attrs={"type": "datetime-local"}, format="%Y-%m-%d %H:%M"
|
attrs={"type": "datetime-local"}, format="%Y-%m-%d %H:%M"
|
||||||
)
|
)
|
||||||
|
autofocus_select_widget = forms.Select(attrs={"autofocus": "autofocus"})
|
||||||
autofocus_input_widget = forms.TextInput(attrs={"autofocus": "autofocus"})
|
autofocus_input_widget = forms.TextInput(attrs={"autofocus": "autofocus"})
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,8 +15,8 @@ class SessionForm(forms.ModelForm):
|
||||||
# queryset=Purchase.objects.filter(date_refunded=None).order_by("edition__name")
|
# queryset=Purchase.objects.filter(date_refunded=None).order_by("edition__name")
|
||||||
# )
|
# )
|
||||||
purchase = forms.ModelChoiceField(
|
purchase = forms.ModelChoiceField(
|
||||||
queryset=Purchase.objects.order_by("edition__sort_name"),
|
queryset=Purchase.objects.order_by("edition__name"),
|
||||||
widget=forms.Select(attrs={"autofocus": "autofocus"}),
|
widget=autofocus_select_widget,
|
||||||
)
|
)
|
||||||
|
|
||||||
device = forms.ModelChoiceField(queryset=Device.objects.order_by("name"))
|
device = forms.ModelChoiceField(queryset=Device.objects.order_by("name"))
|
||||||
|
@ -38,21 +39,12 @@ class SessionForm(forms.ModelForm):
|
||||||
|
|
||||||
class EditionChoiceField(forms.ModelChoiceField):
|
class EditionChoiceField(forms.ModelChoiceField):
|
||||||
def label_from_instance(self, obj) -> str:
|
def label_from_instance(self, obj) -> str:
|
||||||
return f"{obj.sort_name} ({obj.platform}, {obj.year_released})"
|
return f"{obj.name} ({obj.platform}, {obj.year_released})"
|
||||||
|
|
||||||
|
|
||||||
class IncludePlatformSelect(forms.Select):
|
|
||||||
def create_option(self, name, value, *args, **kwargs):
|
|
||||||
option = super().create_option(name, value, *args, **kwargs)
|
|
||||||
if value:
|
|
||||||
option["attrs"]["data-platform"] = value.instance.platform.id
|
|
||||||
return option
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseForm(forms.ModelForm):
|
class PurchaseForm(forms.ModelForm):
|
||||||
edition = EditionChoiceField(
|
edition = EditionChoiceField(
|
||||||
queryset=Edition.objects.order_by("sort_name"),
|
queryset=Edition.objects.order_by("name"), widget=autofocus_select_widget
|
||||||
widget=IncludePlatformSelect(attrs={"autoselect": "autoselect"}),
|
|
||||||
)
|
)
|
||||||
platform = forms.ModelChoiceField(queryset=Platform.objects.order_by("name"))
|
platform = forms.ModelChoiceField(queryset=Platform.objects.order_by("name"))
|
||||||
|
|
||||||
|
@ -75,24 +67,9 @@ class PurchaseForm(forms.ModelForm):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class IncludeNameSelect(forms.Select):
|
|
||||||
def create_option(self, name, value, *args, **kwargs):
|
|
||||||
option = super().create_option(name, value, *args, **kwargs)
|
|
||||||
if value:
|
|
||||||
option["attrs"]["data-name"] = value.instance.name
|
|
||||||
return option
|
|
||||||
|
|
||||||
|
|
||||||
class GameModelChoiceField(forms.ModelChoiceField):
|
|
||||||
def label_from_instance(self, obj):
|
|
||||||
# Use sort_name as the label for the option
|
|
||||||
return obj.sort_name
|
|
||||||
|
|
||||||
|
|
||||||
class EditionForm(forms.ModelForm):
|
class EditionForm(forms.ModelForm):
|
||||||
game = GameModelChoiceField(
|
game = forms.ModelChoiceField(
|
||||||
queryset=Game.objects.order_by("sort_name"),
|
queryset=Game.objects.order_by("name"), widget=autofocus_select_widget
|
||||||
widget=IncludeNameSelect(attrs={"autofocus": "autofocus"}),
|
|
||||||
)
|
)
|
||||||
platform = forms.ModelChoiceField(
|
platform = forms.ModelChoiceField(
|
||||||
queryset=Platform.objects.order_by("name"), required=False
|
queryset=Platform.objects.order_by("name"), required=False
|
||||||
|
@ -100,13 +77,13 @@ class EditionForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Edition
|
model = Edition
|
||||||
fields = ["game", "name", "sort_name", "platform", "year_released", "wikidata"]
|
fields = ["game", "name", "platform", "year_released", "wikidata"]
|
||||||
|
|
||||||
|
|
||||||
class GameForm(forms.ModelForm):
|
class GameForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Game
|
model = Game
|
||||||
fields = ["name", "sort_name", "year_released", "wikidata"]
|
fields = ["name", "year_released", "wikidata"]
|
||||||
widgets = {"name": autofocus_input_widget}
|
widgets = {"name": autofocus_input_widget}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-09 09:32
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
def create_sort_name(apps, schema_editor):
|
|
||||||
Edition = apps.get_model(
|
|
||||||
"games", "Edition"
|
|
||||||
) # Replace 'your_app_name' with the actual name of your app
|
|
||||||
|
|
||||||
for edition in Edition.objects.all():
|
|
||||||
name = edition.name
|
|
||||||
# Check for articles at the beginning of the name and move them to the end
|
|
||||||
if name.lower().startswith("the "):
|
|
||||||
sort_name = f"{name[4:]}, The"
|
|
||||||
elif name.lower().startswith("a "):
|
|
||||||
sort_name = f"{name[2:]}, A"
|
|
||||||
elif name.lower().startswith("an "):
|
|
||||||
sort_name = f"{name[3:]}, An"
|
|
||||||
else:
|
|
||||||
sort_name = name
|
|
||||||
# Save the sort_name back to the database
|
|
||||||
edition.sort_name = sort_name
|
|
||||||
edition.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("games", "0023_purchase_date_finished"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="edition",
|
|
||||||
name="sort_name",
|
|
||||||
field=models.CharField(blank=True, default=None, max_length=255, null=True),
|
|
||||||
),
|
|
||||||
migrations.RunPython(create_sort_name),
|
|
||||||
]
|
|
|
@ -1,39 +0,0 @@
|
||||||
# Generated by Django 4.1.5 on 2023-11-09 09:32
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
def create_sort_name(apps, schema_editor):
|
|
||||||
Game = apps.get_model(
|
|
||||||
"games", "Game"
|
|
||||||
) # Replace 'your_app_name' with the actual name of your app
|
|
||||||
|
|
||||||
for game in Game.objects.all():
|
|
||||||
name = game.name
|
|
||||||
# Check for articles at the beginning of the name and move them to the end
|
|
||||||
if name.lower().startswith("the "):
|
|
||||||
sort_name = f"{name[4:]}, The"
|
|
||||||
elif name.lower().startswith("a "):
|
|
||||||
sort_name = f"{name[2:]}, A"
|
|
||||||
elif name.lower().startswith("an "):
|
|
||||||
sort_name = f"{name[3:]}, An"
|
|
||||||
else:
|
|
||||||
sort_name = name
|
|
||||||
# Save the sort_name back to the database
|
|
||||||
game.sort_name = sort_name
|
|
||||||
game.save()
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("games", "0024_edition_sort_name"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="game",
|
|
||||||
name="sort_name",
|
|
||||||
field=models.CharField(blank=True, default=None, max_length=255, null=True),
|
|
||||||
),
|
|
||||||
migrations.RunPython(create_sort_name),
|
|
||||||
]
|
|
|
@ -10,29 +10,12 @@ from django.db.models import F, Manager, Sum
|
||||||
|
|
||||||
class Game(models.Model):
|
class Game(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
sort_name = models.CharField(max_length=255, null=True, blank=True, default=None)
|
|
||||||
year_released = models.IntegerField(null=True, blank=True, default=None)
|
year_released = models.IntegerField(null=True, blank=True, default=None)
|
||||||
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
# Logic to create sort_name from name
|
|
||||||
def get_sort_name(name):
|
|
||||||
articles = ["a", "an", "the"]
|
|
||||||
name_parts = name.split()
|
|
||||||
first_word = name_parts[0].lower()
|
|
||||||
if first_word in articles:
|
|
||||||
# Move the first word to the end
|
|
||||||
name_parts.append(name_parts.pop(0))
|
|
||||||
return ", ".join(name_parts).capitalize()
|
|
||||||
else:
|
|
||||||
return name.capitalize()
|
|
||||||
|
|
||||||
self.sort_name = get_sort_name(self.name)
|
|
||||||
super().save(*args, **kwargs) # Call the "real" save() method.
|
|
||||||
|
|
||||||
|
|
||||||
class Edition(models.Model):
|
class Edition(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -40,7 +23,6 @@ class Edition(models.Model):
|
||||||
|
|
||||||
game = models.ForeignKey("Game", on_delete=models.CASCADE)
|
game = models.ForeignKey("Game", on_delete=models.CASCADE)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
sort_name = models.CharField(max_length=255, null=True, blank=True, default=None)
|
|
||||||
platform = models.ForeignKey(
|
platform = models.ForeignKey(
|
||||||
"Platform", on_delete=models.CASCADE, null=True, blank=True, default=None
|
"Platform", on_delete=models.CASCADE, null=True, blank=True, default=None
|
||||||
)
|
)
|
||||||
|
@ -48,23 +30,7 @@ class Edition(models.Model):
|
||||||
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
wikidata = models.CharField(max_length=50, null=True, blank=True, default=None)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.sort_name
|
return self.name
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
# Logic to create sort_name from name
|
|
||||||
def get_sort_name(name):
|
|
||||||
articles = ["a", "an", "the"]
|
|
||||||
name_parts = name.split()
|
|
||||||
first_word = name_parts[0].lower()
|
|
||||||
if first_word in articles:
|
|
||||||
# Move the first word to the end
|
|
||||||
name_parts.append(name_parts.pop(0))
|
|
||||||
return ", ".join(name_parts).capitalize()
|
|
||||||
else:
|
|
||||||
return name.capitalize()
|
|
||||||
|
|
||||||
self.sort_name = get_sort_name(self.name)
|
|
||||||
super().save(*args, **kwargs) # Call the "real" save() method.
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseQueryset(models.QuerySet):
|
class PurchaseQueryset(models.QuerySet):
|
||||||
|
|
|
@ -1,18 +1,29 @@
|
||||||
import { syncSelectInputUntilChanged } from './utils.js';
|
/**
|
||||||
|
* @description Sync select field with input field until user focuses it.
|
||||||
|
* @param {HTMLSelectElement} sourceElementSelector
|
||||||
|
* @param {HTMLInputElement} targetElementSelector
|
||||||
|
*/
|
||||||
|
function syncSelectInputUntilChanged(
|
||||||
|
sourceElementSelector,
|
||||||
|
targetElementSelector
|
||||||
|
) {
|
||||||
|
const sourceElement = document.querySelector(sourceElementSelector);
|
||||||
|
const targetElement = document.querySelector(targetElementSelector);
|
||||||
|
function sourceElementHandler(event) {
|
||||||
|
let selected = event.target.value;
|
||||||
|
let selectedValue = document.querySelector(
|
||||||
|
`#id_game option[value='${selected}']`
|
||||||
|
).textContent;
|
||||||
|
targetElement.value = selectedValue;
|
||||||
|
}
|
||||||
|
function targetElementHandler(event) {
|
||||||
|
sourceElement.removeEventListener("change", sourceElementHandler);
|
||||||
|
}
|
||||||
|
|
||||||
let syncData = [
|
sourceElement.addEventListener("change", sourceElementHandler);
|
||||||
{
|
targetElement.addEventListener("focus", targetElementHandler);
|
||||||
"source": "#id_game",
|
}
|
||||||
"source_value": "dataset.name",
|
|
||||||
"target": "#id_name",
|
|
||||||
"target_value": "value"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": "#id_game",
|
|
||||||
"source_value": "textContent",
|
|
||||||
"target": "#id_sort_name",
|
|
||||||
"target_value": "value"
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
syncSelectInputUntilChanged(syncData, "form");
|
window.addEventListener("load", () => {
|
||||||
|
syncSelectInputUntilChanged("#id_game", "#id_name");
|
||||||
|
});
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { syncSelectInputUntilChanged } from './utils.js'
|
|
||||||
|
|
||||||
let syncData = [
|
|
||||||
{
|
|
||||||
"source": "#id_name",
|
|
||||||
"source_value": "value",
|
|
||||||
"target": "#id_sort_name",
|
|
||||||
"target_value": "value"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
syncSelectInputUntilChanged(syncData, "form")
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { syncSelectInputUntilChanged } from './utils.js'
|
|
||||||
|
|
||||||
let syncData = [
|
|
||||||
{
|
|
||||||
"source": "#id_edition",
|
|
||||||
"source_value": "dataset.platform",
|
|
||||||
"target": "#id_platform",
|
|
||||||
"target_value": "value"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
syncSelectInputUntilChanged(syncData, "form")
|
|
|
@ -3,7 +3,7 @@
|
||||||
* @param {Date} date
|
* @param {Date} date
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function toISOUTCString(date) {
|
export function toISOUTCString(date) {
|
||||||
function stringAndPad(number) {
|
function stringAndPad(number) {
|
||||||
return number.toString().padStart(2, 0);
|
return number.toString().padStart(2, 0);
|
||||||
}
|
}
|
||||||
|
@ -14,77 +14,3 @@ function toISOUTCString(date) {
|
||||||
const minutes = stringAndPad(date.getMinutes());
|
const minutes = stringAndPad(date.getMinutes());
|
||||||
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Sync values between source and target elements based on syncData configuration.
|
|
||||||
* @param {Array} syncData - Array of objects to define source and target elements with their respective value types.
|
|
||||||
*/
|
|
||||||
function syncSelectInputUntilChanged(syncData, parentSelector = document) {
|
|
||||||
const parentElement =
|
|
||||||
parentSelector === document
|
|
||||||
? document
|
|
||||||
: document.querySelector(parentSelector);
|
|
||||||
|
|
||||||
if (!parentElement) {
|
|
||||||
console.error(`The parent selector "${parentSelector}" is not valid.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Set up a single change event listener on the document for handling all source changes
|
|
||||||
parentElement.addEventListener("change", function (event) {
|
|
||||||
// Loop through each sync configuration item
|
|
||||||
syncData.forEach((syncItem) => {
|
|
||||||
// Check if the change event target matches the source selector
|
|
||||||
if (event.target.matches(syncItem.source)) {
|
|
||||||
const sourceElement = event.target;
|
|
||||||
const valueToSync = getValueFromProperty(
|
|
||||||
sourceElement,
|
|
||||||
syncItem.source_value
|
|
||||||
);
|
|
||||||
const targetElement = document.querySelector(syncItem.target);
|
|
||||||
|
|
||||||
if (targetElement && valueToSync !== null) {
|
|
||||||
targetElement[syncItem.target_value] = valueToSync;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up a single focus event listener on the document for handling all target focuses
|
|
||||||
parentElement.addEventListener(
|
|
||||||
"focus",
|
|
||||||
function (event) {
|
|
||||||
// Loop through each sync configuration item
|
|
||||||
syncData.forEach((syncItem) => {
|
|
||||||
// Check if the focus event target matches the target selector
|
|
||||||
if (event.target.matches(syncItem.target)) {
|
|
||||||
// Remove the change event listener to stop syncing
|
|
||||||
// This assumes you want to stop syncing once any target receives focus
|
|
||||||
// You may need a more sophisticated way to remove listeners if you want to stop
|
|
||||||
// syncing selectively based on other conditions
|
|
||||||
document.removeEventListener("change", syncSelectInputUntilChanged);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
true
|
|
||||||
); // Use capture phase to ensure the event is captured during focus, not bubble
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Retrieve the value from the source element based on the provided property.
|
|
||||||
* @param {Element} sourceElement - The source HTML element.
|
|
||||||
* @param {string} property - The property to retrieve the value from.
|
|
||||||
*/
|
|
||||||
function getValueFromProperty(sourceElement, property) {
|
|
||||||
let source = (sourceElement instanceof HTMLSelectElement) ? sourceElement.selectedOptions[0] : sourceElement
|
|
||||||
if (property.startsWith("dataset.")) {
|
|
||||||
let datasetKey = property.slice(8); // Remove 'dataset.' part
|
|
||||||
return source.dataset[datasetKey];
|
|
||||||
} else if (property in source) {
|
|
||||||
return source[property];
|
|
||||||
} else {
|
|
||||||
console.error(`Property ${property} is not valid for the option element.`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { toISOUTCString, syncSelectInputUntilChanged };
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %}{{ title }}{% endblock title %}
|
{% block title %}{{ title }}{% endblock title %}
|
||||||
|
|
||||||
|
@ -16,10 +15,3 @@
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
{% block scripts %}
|
|
||||||
{% if script_name %}
|
|
||||||
<script type="module" src="{% static 'js/'|add:script_name %}"></script>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock scripts %}
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}{{ title }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<table class="mx-auto">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{{ form.as_table }}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><input type="submit" value="Submit"/></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{% load static %}
|
||||||
|
<script type="module" src="{% static 'js/add_edition.js' %}"></script>
|
||||||
|
{% endblock scripts %}
|
|
@ -127,7 +127,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h1 class="text-5xl text-center my-6">Finished ({{ year }} games)</h1>
|
<h1 class="text-5xl text-center my-6">Finished (2023 games)</h1>
|
||||||
<table class="responsive-table">
|
<table class="responsive-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -407,7 +407,6 @@ def add_purchase(request):
|
||||||
|
|
||||||
context["form"] = form
|
context["form"] = form
|
||||||
context["title"] = "Add New Purchase"
|
context["title"] = "Add New Purchase"
|
||||||
context["script_name"] = "add_purchase.js"
|
|
||||||
return render(request, "add.html", context)
|
return render(request, "add.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -420,7 +419,6 @@ def add_game(request):
|
||||||
|
|
||||||
context["form"] = form
|
context["form"] = form
|
||||||
context["title"] = "Add New Game"
|
context["title"] = "Add New Game"
|
||||||
context["script_name"] = "add_game.js"
|
|
||||||
return render(request, "add.html", context)
|
return render(request, "add.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@ -433,8 +431,7 @@ def add_edition(request):
|
||||||
|
|
||||||
context["form"] = form
|
context["form"] = form
|
||||||
context["title"] = "Add New Edition"
|
context["title"] = "Add New Edition"
|
||||||
context["script_name"] = "add_edition.js"
|
return render(request, "add_edition.html", context)
|
||||||
return render(request, "add.html", context)
|
|
||||||
|
|
||||||
|
|
||||||
def add_platform(request):
|
def add_platform(request):
|
||||||
|
|
Loading…
Reference in New Issue