Skip to content

Commit

Permalink
Improve names re #10541
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobtylerwalls committed Apr 25, 2024
1 parent c08c009 commit 5ede55a
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Generated by Django 4.2.11 on 2024-03-11 09:39

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("models", "10554_controlled_lists_guide_and_search"),
]

operations = [
migrations.RenameField(
model_name="controlledlistitem",
old_name="list",
new_name="controlled_list",
),
migrations.RenameField(
model_name="controlledlistitemlabel",
old_name="item",
new_name="controlled_list_item",
),
migrations.RemoveConstraint(
model_name="controlledlistitem",
name="unique_list_sortorder",
),
migrations.RemoveConstraint(
model_name="controlledlistitemlabel",
name="unique_item_value_valuetype_language",
),
migrations.RemoveConstraint(
model_name="controlledlistitemlabel",
name="unique_item_preflabel_language",
),
migrations.AlterField(
model_name="controlledlistitem",
name="controlled_list",
field=models.ForeignKey(
db_column="listid",
on_delete=models.deletion.CASCADE,
related_name="controlled_list_items",
to="models.controlledlist",
),
),
migrations.AlterField(
model_name="controlledlistitemlabel",
name="controlled_list_item",
field=models.ForeignKey(
db_column="itemid",
on_delete=models.deletion.CASCADE,
related_name="controlled_list_item_labels",
to="models.controlledlistitem",
),
),
migrations.AddConstraint(
model_name="controlledlistitem",
constraint=models.UniqueConstraint(
deferrable=models.constraints.Deferrable["DEFERRED"],
fields=("controlled_list", "sortorder"),
name="unique_list_sortorder",
),
),
migrations.AddConstraint(
model_name="controlledlistitemlabel",
constraint=models.UniqueConstraint(
fields=("controlled_list_item", "value", "value_type", "language"),
name="unique_item_value_valuetype_language",
),
),
migrations.AddConstraint(
model_name="controlledlistitemlabel",
constraint=models.UniqueConstraint(
condition=models.Q(("value_type", "prefLabel")),
fields=("controlled_list_item", "language"),
name="unique_item_preflabel_language",
),
),
]
16 changes: 8 additions & 8 deletions arches/app/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1877,11 +1877,11 @@ class Meta:
class ControlledListItem(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
uri = models.URLField(max_length=2048, null=True, blank=True, unique=True)
list = models.ForeignKey(
controlled_list = models.ForeignKey(
ControlledList,
db_column="listid",
on_delete=models.CASCADE,
related_name="items",
related_name="controlled_list_items",
)
sortorder = models.IntegerField(validators=[MinValueValidator(0)])
parent = models.ForeignKey(
Expand All @@ -1895,24 +1895,24 @@ class Meta:
# Sort order concerns the list as a whole, not subsets
# of the hierarchy.
models.UniqueConstraint(
fields=["list", "sortorder"],
fields=["controlled_list", "sortorder"],
name="unique_list_sortorder",
deferrable=Deferrable.DEFERRED,
),
]

def clean(self):
if not self.labels.filter(value_type="prefLabel").exists():
if not self.controlled_list_item_labels.filter(value_type="prefLabel").exists():
raise ValidationError(_("At least one preferred label is required."))


class ControlledListItemLabel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
item = models.ForeignKey(
controlled_list_item = models.ForeignKey(
ControlledListItem,
db_column="itemid",
on_delete=models.CASCADE,
related_name="labels",
related_name="controlled_list_item_labels",
)
value_type = models.ForeignKey(
DValueType, on_delete=models.PROTECT, limit_choices_to={"category": "label"}
Expand All @@ -1929,11 +1929,11 @@ class Meta:
db_table = "controlled_list_item_labels"
constraints = [
models.UniqueConstraint(
fields=["item", "value", "value_type", "language"],
fields=["controlled_list_item", "value", "value_type", "language"],
name="unique_item_value_valuetype_language",
),
models.UniqueConstraint(
fields=["item", "language"],
fields=["controlled_list_item", "language"],
condition=Q(value_type="prefLabel"),
name="unique_item_preflabel_language",
),
Expand Down
56 changes: 34 additions & 22 deletions arches/app/src/components/ControlledListManager/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const ERROR = "error";
type GetText = (s: string) => string;

export const postItemToServer = async (
item: ControlledListItem, toast: typeof Toast, $gettext: GetText
item: ControlledListItem,
toast: typeof Toast,
$gettext: GetText
) => {
let errorText;
try {
Expand Down Expand Up @@ -42,27 +44,28 @@ export const postItemToServer = async (
};

export const postListToServer = async (
list: ControlledList, toast: typeof Toast, $gettext: GetText
list: ControlledList,
toast: typeof Toast,
$gettext: GetText
) => {
let errorText;

// need to delete children, as they might prevent
// stringification if circular references exist.
const flatList = {
...list,
items: list.items.map((item) => { return {...item, children: []}; }),
items: list.items.map((item) => {
return { ...item, children: [] };
}),
};
try {
const response = await fetch(
arches.urls.controlled_list(list.id),
{
method: "POST",
headers: {
"X-CSRFToken": Cookies.get("csrftoken"),
},
body: JSON.stringify(flatList),
}
);
const response = await fetch(arches.urls.controlled_list(list.id), {
method: "POST",
headers: {
"X-CSRFToken": Cookies.get("csrftoken"),
},
body: JSON.stringify(flatList),
});
if (!response.ok) {
errorText = response.statusText;
const body = await response.json();
Expand All @@ -78,10 +81,14 @@ export const postListToServer = async (
};

export const upsertLabel = async (
label: NewLabel, toast: typeof Toast, $gettext: GetText
label: NewLabel,
toast: typeof Toast,
$gettext: GetText
) => {
let errorText;
const url = label.id ? arches.urls.label(label.id) : arches.urls.label_add;
const url = label.id
? arches.urls.controlled_list_item_label(label.id)
: arches.urls.controlled_list_item_label_add;
try {
const response = await fetch(url, {
method: "POST",
Expand All @@ -107,16 +114,21 @@ export const upsertLabel = async (
};

export const deleteLabel = async (
label: Label, toast: typeof Toast, $gettext: GetText
label: Label,
toast: typeof Toast,
$gettext: GetText
) => {
let errorText;
try {
const response = await fetch(arches.urls.label(label.id), {
method: "DELETE",
headers: {
"X-CSRFToken": Cookies.get("csrftoken"),
},
});
const response = await fetch(
arches.urls.controlled_list_item_label(label.id),
{
method: "DELETE",
headers: {
"X-CSRFToken": Cookies.get("csrftoken"),
},
}
);
if (!response.ok) {
errorText = response.statusText;
const body = await response.json();
Expand Down
4 changes: 2 additions & 2 deletions arches/app/templates/javascript.htm
Original file line number Diff line number Diff line change
Expand Up @@ -1071,8 +1071,8 @@
controlled_list_add="{% url 'controlled_list_add' %}"
controlled_list_item='(itemid) => {return "{% url "controlled_list_item" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" %}".replace("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", itemid)}'
controlled_list_item_add="{% url 'controlled_list_item_add' %}"
label='(labelid) => {return "{% url "label" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" %}".replace("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", labelid)}'
label_add="{% url 'label_add' %}"
controlled_list_item_label='(labelid) => {return "{% url "controlled_list_item_label" "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" %}".replace("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", labelid)}'
controlled_list_item_label_add="{% url 'controlled_list_item_label_add' %}"
></div>
{% endblock arches_urls %}
{% block arches_data %}
Expand Down
48 changes: 30 additions & 18 deletions arches/app/views/controlled_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def serialize(obj, depth_map=None, flat=False, nodes=False):
"items": sorted(
[
serialize(item, depth_map, flat)
for item in obj.items.all()
for item in obj.controlled_list_items.all()
if flat or item.parent_id is None
],
key=lambda d: d["sortorder"],
Expand Down Expand Up @@ -85,7 +85,10 @@ def serialize(obj, depth_map=None, flat=False, nodes=False):
"uri": obj.uri,
"sortorder": obj.sortorder,
"guide": obj.guide,
"labels": [serialize(label, depth_map) for label in obj.labels.all()],
"labels": [
serialize(label, depth_map)
for label in obj.controlled_list_item_labels.all()
],
"parent_id": str(obj.parent_id) if obj.parent_id else None,
"depth": depth_map[obj.id],
}
Expand All @@ -101,7 +104,7 @@ def serialize(obj, depth_map=None, flat=False, nodes=False):
"valuetype": obj.value_type_id,
"language": obj.language_id,
"value": obj.value,
"item_id": obj.item_id,
"item_id": obj.controlled_list_item_id,
}


Expand All @@ -114,10 +117,18 @@ def prefetch_terms(request):
terms = []
for i in range(prefetch_depth):
if i == 0:
terms.extend(["items", "items__labels"])
terms.extend(
[
"controlled_list_items",
"controlled_list_items__controlled_list_item_labels",
]
)
elif find_children:
terms.extend(
[f"items{'__children' * i}", f"items{'__children' * i}__labels"]
[
f"controlled_list_items{'__children' * i}",
f"controlled_list_items{'__children' * i}__controlled_list_item_labels",
]
)
return terms

Expand Down Expand Up @@ -145,7 +156,7 @@ def handle_item(item_dict):
label["value_type_id"] = label.pop("valuetype")
label.pop("item_id") # trust the item, not the label
labels_to_save.append(
ControlledListItemLabel(item_id=item_to_save.id, **label)
ControlledListItemLabel(controlled_list_item_id=item_to_save.id, **label)
)

# Recurse
Expand All @@ -157,8 +168,8 @@ def handle_item(item_dict):

# Consider skipping uniqueness checks and just letting IntegrityError
# bubble up. But doing Django validation provides a localized error.
for itemDict in items_to_save:
item_to_save.full_clean(exclude=["parent", "list", "id"])
for item_to_save in items_to_save:
item_to_save.full_clean(exclude=["parent", "controlled_list", "id"])

ControlledListItem.objects.bulk_update(
items_to_save, fields=["uri", "sortorder", "parent"]
Expand Down Expand Up @@ -197,8 +208,7 @@ def get(self, request):
@staticmethod
def node_subquery(node_field: str = "pk"):
return ArraySubquery(
Node.with_controlled_list
.filter(controlled_list=OuterRef("id"))
Node.with_controlled_list.filter(controlled_list=OuterRef("id"))
.order_by("pk")
.values(node_field)
)
Expand Down Expand Up @@ -244,16 +254,16 @@ def post(self, request, **kwargs):
data = JSONDeserializer().deserialize(request.body)

qs = (
ControlledListItem.objects.filter(list_id=list_id)
.select_related("list")
ControlledListItem.objects.filter(controlled_list_id=list_id)
.select_related("controlled_list")
.select_for_update()
)
# TODO: lock labels?
# Does not currently bother to lock labels.

try:
with transaction.atomic():
try:
clist = qs[0].list
clist = qs[0].controlled_list
except (IndexError, ControlledListItem.DoesNotExist):
clist = ControlledList.objects.get(pk=list_id)
except ControlledList.DoesNotExist:
Expand All @@ -264,7 +274,7 @@ def post(self, request, **kwargs):
clist.name = data["name"]

for item in data["items"]:
item["list_id"] = list_id
item["controlled_list_id"] = list_id
handle_items(data["items"])

clist.save()
Expand Down Expand Up @@ -374,12 +384,12 @@ def delete(self, request, **kwargs):
@method_decorator(
group_required("RDM Administrator", raise_exception=True), name="dispatch"
)
class LabelView(View):
class ControlledListItemLabelView(View):
def add_new_label(self, request):
data = JSONDeserializer().deserialize(request.body)

label = ControlledListItemLabel(
item_id=data["item_id"],
controlled_list_item_id=data["item_id"],
value_type_id=data["valuetype"],
language=Language.objects.get(code=data["language"]),
value=data["value"],
Expand Down Expand Up @@ -417,7 +427,9 @@ def post(self, request, **kwargs):

def delete(self, request, **kwargs):
label_id = kwargs.get("id")
objs_deleted, unused = ControlledListItemLabel.objects.filter(pk=label_id).delete()
objs_deleted, unused = ControlledListItemLabel.objects.filter(
pk=label_id
).delete()
if not objs_deleted:
return JSONErrorResponse(status=404)
return JSONResponse(status=204)
Loading

0 comments on commit 5ede55a

Please sign in to comment.