Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge staging into production, 6 March 2025 #1782

Open
wants to merge 36 commits into
base: production
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d361784
fix: unaccent holding institution name in browse sources search
lucasmarchd01 Jan 23, 2025
e637960
feat: ad quoted search for exact field matching
lucasmarchd01 Jan 23, 2025
f4007df
fix: fix regex expression, remove accent characters
lucasmarchd01 Jan 24, 2025
801c592
test: add tests for exact quote searching on SourceListViewTest
lucasmarchd01 Jan 24, 2025
57fca3e
refactor: add typing
lucasmarchd01 Jan 24, 2025
f977369
refactor: add typing
lucasmarchd01 Jan 24, 2025
c921a37
Merge branch 'issue-1632' of https://github.com/lucasmarchd01/CantusD…
lucasmarchd01 Jan 24, 2025
8db4904
Merge branch 'develop' into issue-1632
lucasmarchd01 Jan 24, 2025
6dd3880
fix: change quoted search query to use icontains instead of iexact
lucasmarchd01 Jan 30, 2025
a8fbfc6
feat: add markdown field widget
dchiller Jan 31, 2025
3cc4d47
Add comment to helper_tags.render_markdown
dchiller Feb 3, 2025
a6af78e
Merge pull request #1737 from lucasmarchd01/issue-1632
lucasmarchd01 Feb 5, 2025
1e7d0b7
Merge pull request #1749 from dchiller/markdown-fields
dchiller Feb 5, 2025
c05f28f
feat: add credit for source descriptions
lucasmarchd01 Feb 6, 2025
908d5b4
fix: uncomment description_entered_by field in admin model form
lucasmarchd01 Feb 7, 2025
355aef1
Merge pull request #1758 from lucasmarchd01/issue-1732
lucasmarchd01 Feb 7, 2025
24188c4
fix(chant detail format): add missing closing tag
dchiller Feb 7, 2025
151035a
Merge pull request #1763 from DDMAL/i1760-missing-close-b-tag
dchiller Feb 7, 2025
e1e7ede
feat: add bulk edit functionality to `SourceBrowseChantsView`
dchiller Feb 26, 2025
6c03d62
fix: Use IntegerField for c_sequence in Chant Create and Edit
dchiller Feb 26, 2025
e360b9b
fix: replace missing `User` type import in test_views/test_source
dchiller Feb 26, 2025
47b3889
Merge pull request #1768 from dchiller/i1714-bulk-chant-edit
dchiller Feb 27, 2025
3641fbb
fix(BaseAdmin): add typing to BaseAdmin class
dchiller Feb 4, 2025
972c4a1
fix: replace DACT logos
dchiller Feb 5, 2025
53d934f
fix(css): move all css to static/css
dchiller Feb 5, 2025
0e5a944
feat: add management commands to populate segment_m2m field
dchiller Mar 3, 2025
1ed26c0
fix(make_fakes): add segment values to segment_m2m field
dchiller Mar 3, 2025
a5fd19b
feat: add Canadian Chant DB landing page
dchiller Mar 3, 2025
38aaf98
Merge pull request #1772 from dchiller/landing-pages
dchiller Mar 3, 2025
bb764db
Merge pull request #1773 from DDMAL/develop
dchiller Mar 3, 2025
c87a549
fix(sshrc logo): replace sshrc jpg logo with png
dchiller Mar 5, 2025
604593b
refactor(single column search bar template): change header block to h…
dchiller Mar 5, 2025
e953dfa
fix: serve CCDB homepage sustainably
dchiller Mar 5, 2025
9630b6b
fix: update SourceListViewTest with new template location
dchiller Mar 5, 2025
54a204d
Merge pull request #1779 from dchiller/landing-pages
dchiller Mar 5, 2025
06a6847
Merge pull request #1780 from DDMAL/develop
dchiller Mar 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion django/cantusdb_project/main_app/admin/base_admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Tuple

from reversion.admin import VersionAdmin


Expand All @@ -15,7 +17,7 @@

class BaseModelAdmin(VersionAdmin):
exclude = EXCLUDE
readonly_fields = READ_ONLY
readonly_fields: Tuple[str, ...] = READ_ONLY

# if an object is created in the admin interface, assign the user to the created_by field
# else if an object is updated in the admin interface, assign the user to the last_updated_by field
Expand Down
1 change: 1 addition & 0 deletions django/cantusdb_project/main_app/admin/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class SourceAdmin(BaseModelAdmin):
"inventoried_by",
"full_text_entered_by",
"melodies_entered_by",
"description_entered_by",
"proofreaders",
"other_editors",
)
Expand Down
81 changes: 75 additions & 6 deletions django/cantusdb_project/main_app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
VolpianoAreaWidget,
SelectWidget,
CheckboxWidget,
MarkdownWidget,
)

# ModelForm allows to build a form directly from a model
Expand Down Expand Up @@ -213,7 +214,7 @@ class Meta:
help_text="Binding order",
)

c_sequence = forms.CharField(
c_sequence = forms.IntegerField(
required=True,
widget=TextInputWidget,
help_text="Each folio starts with '1'.",
Expand Down Expand Up @@ -279,6 +280,7 @@ class Meta:
"melodies_entered_by",
"inventoried_by",
"full_text_entered_by",
"description_entered_by",
"proofreaders",
"other_editors",
"complete_inventory",
Expand All @@ -305,8 +307,8 @@ class Meta:
"date": TextInputWidget(),
"cursus": SelectWidget(),
"summary": TextAreaWidget(),
"description": TextAreaWidget(),
"selected_bibliography": TextAreaWidget(),
"description": MarkdownWidget(),
"selected_bibliography": MarkdownWidget(),
"image_link": TextInputWidget(),
"fragmentarium_id": TextInputWidget(),
"dact_id": TextInputWidget(),
Expand All @@ -324,6 +326,9 @@ class Meta:
"full_text_entered_by": autocomplete.ModelSelect2Multiple(
url="all-users-autocomplete"
),
"description_entered_by": autocomplete.ModelSelect2Multiple(
url="all-users-autocomplete"
),
"proofreaders": autocomplete.ModelSelect2Multiple(
url="all-users-autocomplete"
),
Expand Down Expand Up @@ -436,7 +441,7 @@ class Meta:
help_text="Binding order",
)

c_sequence = forms.CharField(
c_sequence = forms.IntegerField(
required=True,
widget=TextInputWidget,
help_text="Each folio starts with '1'.",
Expand Down Expand Up @@ -517,6 +522,7 @@ class Meta:
"melodies_entered_by",
"inventoried_by",
"full_text_entered_by",
"description_entered_by",
"proofreaders",
"other_editors",
"production_method",
Expand All @@ -535,8 +541,8 @@ class Meta:
"cursus": SelectWidget(),
"summary": TextAreaWidget(),
"liturgical_occasions": TextAreaWidget(),
"description": TextAreaWidget(),
"selected_bibliography": TextAreaWidget(),
"description": MarkdownWidget(),
"selected_bibliography": MarkdownWidget(),
"image_link": TextInputWidget(),
"fragmentarium_id": TextInputWidget(),
"dact_id": TextInputWidget(),
Expand All @@ -554,6 +560,9 @@ class Meta:
"full_text_entered_by": autocomplete.ModelSelect2Multiple(
url="all-users-autocomplete"
),
"description_entered_by": autocomplete.ModelSelect2Multiple(
url="all-users-autocomplete"
),
"proofreaders": autocomplete.ModelSelect2Multiple(
url="all-users-autocomplete"
),
Expand Down Expand Up @@ -891,6 +900,14 @@ class Meta:
),
)

description_entered_by = forms.ModelMultipleChoiceField(
queryset=get_user_model().objects.all().order_by("full_name"),
required=False,
widget=FilteredSelectMultiple(
verbose_name="description entered by", is_stacked=False
),
)

melodies_entered_by = forms.ModelMultipleChoiceField(
queryset=get_user_model().objects.all().order_by("full_name"),
required=False,
Expand Down Expand Up @@ -967,3 +984,55 @@ def save(self, source: Source) -> None:
for folio, image_link in cleaned_data.items():
if image_link != "":
source.chant_set.filter(folio=folio).update(image_link=image_link)

class BrowseChantsBulkEditForm(forms.ModelForm):
class Meta:
model = Chant
fields = [
"id",
"folio",
"c_sequence",
"manuscript_full_text_std_spelling",
"feast",
"service",
"genre",
"position",
"cantus_id",
"mode",
]
widgets = {
"id": HiddenInput(),
"feast": autocomplete.ModelSelect2(url="feast-autocomplete"),
"service": autocomplete.ModelSelect2(url="service-autocomplete"),
"genre": autocomplete.ModelSelect2(url="genre-autocomplete"),
"position": TextInputWidget(),
"cantus_id": TextInputWidget(),
"mode": TextInputWidget(),
}

folio = forms.CharField(
required=True,
widget=TextInputWidget,
)

c_sequence = forms.IntegerField(
required=True,
widget=TextInputWidget,
)

manuscript_full_text_std_spelling = CantusDBLatinField(
widget=TextAreaWidget,
required=True,
)


BrowseChantsBulkEditFormset = forms.inlineformset_factory(
Source,
Chant,
form=BrowseChantsBulkEditForm,
extra=0,
max_num=100,
can_delete=False,
can_order=False,
edit_only=True,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import Any

from django.core.management.base import BaseCommand
from main_app.models import Source


class Command(BaseCommand):
help = "Make changes to the Source model"

def handle(self, *args: Any, **kwargs: Any) -> None:

sources = Source.objects.all()
for source in sources:
source.segment_m2m.add(source.segment)
source.save()

self.stdout.write(
self.style.SUCCESS("Successfully updated Source model with segments")
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from typing import Any
from django.core.management.base import BaseCommand
from main_app.models import Source, Segment


class Command(BaseCommand):
def handle(self, *args: Any, **options: Any) -> None:
ccdb_segment = Segment.objects.get(name="Canadian Chant Database")
canadian_sources = Source.objects.filter(holding_institution__country="Canada")
for source in canadian_sources:
source.segment_m2m.add(ccdb_segment)
source.save()
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.2.16 on 2025-02-06 17:34

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("main_app", "0034_alter_source_source_completeness"),
]

operations = [
migrations.AddField(
model_name="source",
name="description_entered_by",
field=models.ManyToManyField(
blank=True,
related_name="entered_description_for_sources",
to=settings.AUTH_USER_MODEL,
),
),
]
5 changes: 4 additions & 1 deletion django/cantusdb_project/main_app/models/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class SourceCompletenessChoices(models.IntegerChoices):
)

######
# The following five fields have nothing to do with user permissions,
# The following six fields have nothing to do with user permissions,
# instead they give credit to users who are indexers and are displayed
# on the user detail page as sources the user has contributed to.
inventoried_by = models.ManyToManyField(
Expand All @@ -118,6 +118,9 @@ class SourceCompletenessChoices(models.IntegerChoices):
melodies_entered_by = models.ManyToManyField(
get_user_model(), related_name="entered_melody_for_sources", blank=True
)
description_entered_by = models.ManyToManyField(
get_user_model(), related_name="entered_description_for_sources", blank=True
)
proofreaders = models.ManyToManyField(
get_user_model(), related_name="proofread_sources", blank=True
)
Expand Down
87 changes: 81 additions & 6 deletions django/cantusdb_project/main_app/templates/browse_chants.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
{% extends "base_page_with_side_cards.html" %}
{% load static %}
{% block title %}<title>Browse Chants | Cantus Database</title>{% endblock %}
{% block scripts %}<script src="/static/js/chant_list.js"></script>{% endblock %}
{% block scripts %}
<script src="/static/js/chant_list.js"></script>
<script type="text/javascript"
src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
<link rel="stylesheet"
href="{% static 'css/browse_chants_bulk_edit.css' %}" />
{{ bulk_edit_formset.media }}
{{ user_can_edit_chant|json_script:"data-user-can-edit-chants" }}
{% endblock %}
{% block uppersidebar %}
<div class="search-bar mb-3">{% include "global_search_bar.html" %}</div>
{% endblock %}
{% block maincontent %}
<!--Display messages -->
{% for message in messages %}
<div class="alert {{ message.tags }} alert-dismissible" role="alert">
<a href="#" class="close" data-bs-dismiss="alert" aria-label="close">×</a>
{{ message }}
</div>
{% endfor %}
<!--Display form error message -->
{% if bulk_edit_formset.errors %}
<div class="alert alert-danger alert-dismissible">
<a href="#" class="close" data-bs-dismiss="alert" aria-label="close">×</a>
{% for error in bulk_edit_formset.errors %}<div>{{ error }}</div>{% endfor %}
</div>
{% endif %}
<h3>Browse Chants</h3>
<span class="small">Displaying {{ page_obj.start_index }}-{{ page_obj.end_index }} of <b>{{ page_obj.paginator.count }}</b> chants.</span>
<form method="get">
Expand All @@ -18,7 +41,8 @@ <h3>Browse Chants</h3>
class="form-control form-control-sm form-select form-select-sm">
{% comment %} <option value="">- Any -</option> {% endcomment %}
{% for source_obj in sources %}
<option value="{{ source_obj.id }}"{% if source_obj.id == source.id %} selected {% endif %}>{{ source_obj.short_heading }}</option>
<option value="{{ source_obj.id }}"
{% if source_obj.id == source.id %}selected{% endif %}>{{ source_obj.short_heading }}</option>
{% endfor %}
</select>
</div>
Expand Down Expand Up @@ -85,9 +109,21 @@ <h3>Browse Chants</h3>
</fieldset>
{% endif %}
</form>
{% if user_can_edit_chant %}
<div class="text-end mb-3">
<button id="bulkChantEditToggle" type="button" class="btn btn-sm btn-primary">
Bulk Edit Chants
</button>
<button id="bulkChantEditSubmit"
type="submit"
form="bulkChantEditForm"
class="btn btn-sm btn-dark d-none">Save Changes</button>
</div>
{% endif %}
{% with exists_on_cantus_ultimus=source.exists_on_cantus_ultimus %}
{% if chants %}
<table class="table table-responsive table-sm table-bordered small">
<table id="chantDisplayTable"
class="table table-responsive table-sm table-bordered small">
<thead>
<tr>
<th scope="col" class="text-wrap" title="Folio">Folio</th>
Expand Down Expand Up @@ -164,9 +200,48 @@ <h3>Browse Chants</h3>
{% endfor %}
</tbody>
</table>
<div class="small">
{% include "pagination.html" %}
</div>
{% if user_can_edit_chant %}
<form id="bulkChantEditForm" class="d-none" method="post">
{% csrf_token %}
{{ bulk_edit_formset.management_form }}
<div class="table-responsive">
<table class="table table-sm table-bordered small edit-table">
<thead>
<tr>
<th scope="col" class="sm-edit-col" title="Folio">Folio</th>
<th scope="col" class="sm-edit-col" title="Sequence">Seq.</th>
<th scope="col" class="full-text-edit-col" title="Full text">
Full text (Standard Spelling)
</th>
<th scope="col" class="autocomplete-edit-col" title="Feast">Feast</th>
<th scope="col" class="autocomplete-edit-col" title="Service">Service</th>
<th scope="col" class="autocomplete-edit-col" title="Genre">Genre</th>
<th scope="col" class="sm-edit-col" title="Position">Position</th>
<th scope="col" class="med-edit-col" title="Cantus ID">CantusID</th>
<th scope="col" class="sm-edit-col" title="Mode">Mode</th>
</tr>
</thead>
<tbody>
{% for form in bulk_edit_formset %}
<tr>
{{ form.id }}
<td class="text-wrap text-center">{{ form.folio }}</td>
<td class="text-wrap text-center">{{ form.c_sequence }}</td>
<td class="text-wrap">{{ form.manuscript_full_text_std_spelling }}</td>
<td class="text-wrap text-center">{{ form.feast }}</td>
<td class="text-wrap text-center">{{ form.service }}</td>
<td class="text-wrap text-center">{{ form.genre }}</td>
<td class="text-wrap text-center">{{ form.position }}</td>
<td class="text-wrap text-center">{{ form.cantus_id }}</td>
<td class="text-wrap text-center">{{ form.mode }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
{% endif %}
<div class="small">{% include "pagination.html" %}</div>
{% else %}
No chants found.
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{% extends "single_column_with_search_bar.html" %}
{% block title %}<title>{{ century.name }} | Cantus Database</title>{% endblock %}
{% block header %}<h3>{{ century.name }}</h3>{% endblock %}
{% block heading %}<h3>{{ century.name }}</h3>{% endblock %}
{% block maincontent %}
<ul>
{% for source in sources %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ <h4>Melodies</h4>
<a href="https://cantus.simssa.ca/manuscript/{{ chant.source.id }}/?folio={{ chant.folio }}&chant={{ chant.c_sequence }}"
class="guillemet"
target="_blank">
Display facsimile <b>({{ chant.folio }})
Display facsimile <b>({{ chant.folio }})</b>
</a>
{% elif chant.image_link %}
<a href={{ chant.image_link }} class="guillemet" target="_blank">Display facsimile <b>({{ chant.folio }})</b></a>
Expand Down
Loading
Loading