Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2b652c3
First working version of suggestions module
anusharanganathan Feb 4, 2025
0c497d3
Update to include filtering of displayed data
anusharanganathan Feb 5, 2025
7f906b2
Code cleanup, bugfix to search filter
anusharanganathan Feb 5, 2025
a95c1fb
Remove file no longer needed
anusharanganathan Feb 5, 2025
2ff7abf
Commiting migrations
anusharanganathan Feb 11, 2025
9de3d9a
Set inital value of status to New
anusharanganathan Feb 11, 2025
d1e5e17
Add csrf token to form
anusharanganathan Feb 11, 2025
45ff9ff
Using get for record and redirect to all suggestions
anusharanganathan Feb 11, 2025
717b458
Fix for URL redirection
anusharanganathan Feb 11, 2025
64c4d28
Fixes to redirect for edit and delete
anusharanganathan Feb 11, 2025
fdbf63b
Make message warning instead of success for edit not okay
anusharanganathan Feb 11, 2025
c35c4b1
Minor fixes to messages
anusharanganathan Feb 11, 2025
b0c5e97
Added alert box and created smaller template files
anusharanganathan Feb 11, 2025
696e51b
Matched display to list of suggestions
anusharanganathan Feb 11, 2025
fcd6390
Added property is_updated
anusharanganathan Feb 11, 2025
839447f
Fix crated-updated date time comparison
anusharanganathan Feb 12, 2025
1bb27e1
Code refactoring and UI improvements
anusharanganathan Feb 12, 2025
50178fc
Initial work on resolve
anusharanganathan Feb 13, 2025
7f39166
Small update to setting initial values in person form
anusharanganathan Feb 13, 2025
00b942c
pass suggestion to person form
anusharanganathan Feb 13, 2025
28b280e
Remove CSRF filter for GET, f_filter in url
anusharanganathan Feb 13, 2025
03c56d5
Fix for initial value of month
anusharanganathan Feb 13, 2025
ac81b07
Code refactoring for person-suggestion link
anusharanganathan Feb 14, 2025
9293bb0
Need person_suggestion_fields
anusharanganathan Feb 14, 2025
52b4cb5
Get the resolve button working in suggestion views
anusharanganathan Feb 14, 2025
d8e3d7b
Bug fixes for resolve button
anusharanganathan Feb 14, 2025
7a58950
Add new field suggestion_related_record_int
anusharanganathan Feb 14, 2025
a1a01d8
Implement person suggestion resolution with related link to person re…
anusharanganathan Feb 14, 2025
c5ef7d2
Housekeeping : gitignore and suggestion model migrations
anusharanganathan Feb 14, 2025
e63799d
Ensure resolved suggestion cannot be used again
anusharanganathan Feb 19, 2025
0bd638c
Ensure migrations run if needed
anusharanganathan Feb 19, 2025
5261a60
Ensure migrations run if needed - add entrypoint file
anusharanganathan Feb 19, 2025
a93ea68
Code refacotring for function reuse
anusharanganathan Feb 19, 2025
463bdd3
Working version for suggestion-location resolve connection
anusharanganathan Feb 19, 2025
c599d7f
Bug fix - change person to location
anusharanganathan Feb 19, 2025
6ec1682
Working version for suggestion-instution resolve connection
anusharanganathan Feb 19, 2025
3ceb3c7
Working version for suggestion-publication resolve connection
anusharanganathan Feb 19, 2025
0cb0245
Code cleanup
anusharanganathan Feb 19, 2025
3da240a
Remove unused texts.py file
anusharanganathan Feb 19, 2025
a6e7167
Sharing templates between list and record view
anusharanganathan Feb 21, 2025
686502b
Merge branch 'develop' of https://github.com/culturesofknowledge/site…
RK206 Feb 25, 2025
a74ba6e
Minor fixes
RK206 Feb 26, 2025
c443ffb
Only the author and supervisor can delete the suggestion
RK206 Feb 26, 2025
3071d32
removed all migrations and created single migration
RK206 Feb 26, 2025
84b13c2
removed 'suggestion_related_record' which is not necessary
RK206 Feb 26, 2025
e6d446e
updated Suggestions model
RK206 Feb 27, 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
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dist/*
.idea
# vim swap files
.*.swp
.vscode

# Unit test / coverage reports
htmlcov/*
Expand Down Expand Up @@ -52,7 +53,7 @@ siteedit2/settings/local_test.py
siteedit2/settings/gunweb.py
# */migrations

static/core/scss/
static
core/static/core/scss/main.css
core/management/commands/playground.py
upload/
upload/
Empty file.
3 changes: 3 additions & 0 deletions core/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
PM_CHANGE_ORGTYPE = 'core.change_cofkunionorgtype'
PM_CHANGE_COLLECTWORK = 'uploader.change_cofkcollectwork'
PM_CHANGE_LANGUAGE = 'core.change_iso639languagecode'
PM_CHANGE_SUGGESTIONS = 'suggestions.change_cofksuggestions'
PM_VIEW_SUGGESTIONS = 'suggestions.view_cofksuggestions'
PM_ADD_SUGGESTIONS = 'suggestions.add_cofksuggestions'

PM_CHANGE_USER = 'login.change_cofkuser'
PM_CHANGE_COMMENT = 'core.change_cofkunioncomment'
Expand Down
8 changes: 6 additions & 2 deletions core/management/commands/add_groups_and_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ def handle(self, *args, **kwargs):
constant.PM_CHANGE_SUBJECT,
constant.PM_CHANGE_ORGTYPE,
constant.PM_CHANGE_COLLECTWORK,
constant.PM_CHANGE_LANGUAGE
constant.PM_CHANGE_LANGUAGE,
constant.PM_ADD_SUGGESTIONS,
constant.PM_VIEW_SUGGESTIONS,
],
}
group_permissions_dict[constant.ROLE_SUPER] = group_permissions_dict[constant.ROLE_EDITOR] + [
Expand All @@ -43,7 +45,9 @@ def handle(self, *args, **kwargs):
]
group_permissions_dict[constant.ROLE_CONTRIBUTING_EDITOR] = [
constant.PM_CHANGE_WORK,
constant.PM_VIEW_LOOKUPCAT
constant.PM_VIEW_LOOKUPCAT,
constant.PM_VIEW_SUGGESTIONS,
constant.PM_CHANGE_SUGGESTIONS,
]

# add permissions to groups
Expand Down
18 changes: 18 additions & 0 deletions core/migrations/0012_alter_iso639languagecode_language_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.0.6 on 2025-02-26 03:59

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0011_cofklookupcatalogue_owner'),
]

operations = [
migrations.AlterField(
model_name='iso639languagecode',
name='language_id',
field=models.IntegerField(unique=True),
),
]
27 changes: 27 additions & 0 deletions core/static/core/scss/components/alert.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.alert {
padding: 20px;
background-color: #f44336;
color: white;
opacity: 1;
transition: opacity 0.6s;
margin-bottom: 15px;
}

.alert.success {background-color: #04AA6D;}
.alert.info {background-color: #2196F3;}
.alert.warning {background-color: #ff9800;}

.closebtn {
margin-left: 15px;
color: white;
font-weight: bold;
float: right;
font-size: 22px;
line-height: 20px;
cursor: pointer;
transition: 0.3s;
}

.closebtn:hover {
color: black;
}
26 changes: 26 additions & 0 deletions core/static/core/scss/emlo-common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -461,5 +461,31 @@ $del-red: #800000;
font-weight: bold;
}

.right {
float: right;
margin-right: 20px;
}

.padding-right {
padding-right: 10px;
}

table.suggestion thead tr th {
background-color: lightgray;
font-weight: bold;
}

table.suggestion tbody tr th {
width: 30%;
}

.suggestion-buttons {
margin-bottom: 20px;
}

.btn-text-width {
width: fit-content;
}
input.btn-text-width {
padding: 0px 5px;
}
1 change: 1 addition & 0 deletions core/static/core/scss/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@import 'components/upload.scss';
@import 'components/lookup.scss';
@import 'components/dashboard.scss';
@import 'components/alert.scss';

@import "page-header";
@import "page-footer";
Expand Down
28 changes: 28 additions & 0 deletions core/templates/core/component/alert.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script>
$( window ).on( "load", function() {
var close = document.getElementsByClassName('closebtn');
var i;
for (i = 0; i < close.length; i++) {
close[i].onclick = function(){
var div = this.parentElement;
div.style.opacity = "0";
setTimeout(function(){ div.style.display = "none"; }, 600);
}
}
});
</script>

{% if messages %}
{% for message in messages %}
<div class="alert success">
<span class="closebtn">&times;</span>
<strong>Success! </strong>{{message}}
</div>
{% endfor %}
{% endif %}
{% if message %}
<div class="alert success">
<span class="closebtn">&times;</span>
<strong>Success! </strong>{{message}}
</div>
{% endif %}
6 changes: 6 additions & 0 deletions core/templates/core/emlo_logined.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
{% include "core/component/common_section_search_menu.html" %}
{% include "core/component/common_section_new_menu.html" %}

{% if constant.PM_VIEW_SUGGESTIONS in perms %}
<li class="menu-item">
<a href="{% url 'suggestions:suggestion_all' %}" title="Make a suggestion" target="_self" >Suggestions</a>
</li>
{% endif %}

{% if constant.PM_VIEW_LOOKUPCAT in perms %}
<li class="menu-item">
<a href="">Lists</a>
Expand Down
5 changes: 2 additions & 3 deletions docker/site-edit-2/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.3"

services:

db:
Expand All @@ -26,7 +24,7 @@ services:
- .env
depends_on:
- db
command: python manage.py runserver 0.0.0.0:8000
entrypoint: /code/docker/site-edit-2/entrypoint.sh

django-q:
build:
Expand All @@ -43,4 +41,5 @@ services:

volumes:
data:
old_data:
emlo_home:
10 changes: 10 additions & 0 deletions docker/site-edit-2/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
echo "Making migrations"
python manage.py makemigrations
# Make migrations
echo "Migrating"
python manage.py migrate
# Create cache table
echo "Creating cache table"
python manage.py createcachetable
python -u manage.py runserver 0.0.0.0:8000
31 changes: 31 additions & 0 deletions institution/institution_suggestion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import dateutil.parser
import logging
from dateutil.parser import ParserError
from django.core.exceptions import ObjectDoesNotExist
from suggestions.models import CofkSuggestions
from suggestions import utils as sug_utils
from institution import institution_suggestion_fields

log = logging.getLogger(__name__)

class InstitutionSuggestion:
def __init__(self, suggestion_id):
self.suggestion_id = suggestion_id

def initial_form_values(self):
form_values = {}
try:
sug = CofkSuggestions.objects.get(pk=self.suggestion_id)
if sug.suggestion_status == "Resolved":
log.debug(f"{sug.suggestion_type} suggestion id {sug.suggestion_id} is already in status {sug.suggestion_status}")
return form_values
except ObjectDoesNotExist:
return form_values
parsed_suggestion = sug.parsed_suggestion
for field,sug_value in parsed_suggestion.items():
form_field = sug_utils.suggestion_fields_dict(institution_suggestion_fields.suggestion_fields_map()).get(field, None)
if form_field and sug_value:
form_values[form_field] = sug_value
if form_values:
form_values['editors_notes'] = f"From suggestion {sug.suggestion_id}\n{sug.suggestion_suggestion}"
return form_values
7 changes: 7 additions & 0 deletions institution/institution_suggestion_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def suggestion_fields_map():
return(
("Institution Name", "institution_name"),
("Alternative institution name", "institution_synonyms"),
("City", "institution_city"),
("Country", "institution_country"),
)
19 changes: 19 additions & 0 deletions institution/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from institution.models import CofkUnionInstitution
from institution.recref_adapter import InstResourceRecrefAdapter, InstImageRecrefAdapter
from institution.view_components import InstFormDescriptor
from institution.institution_suggestion import InstitutionSuggestion
from suggestions import views as sug_view

if TYPE_CHECKING:
from core.helper.view_serv import MergeChoiceContext
Expand Down Expand Up @@ -125,12 +127,29 @@ def resp_form_page(self, request, form):
return render(request, 'institution/init_form.html', {'inst_form': form})

def resp_after_saved(self, request, form, new_instance):
suggestion_id = request.GET.get('from_suggestion', None)
if suggestion_id:
sug_view.save_with_related_info(suggestion_id, new_instance.institution_id)
return redirect('institution:full_form', new_instance.institution_id)

@property
def form_factory(self) -> Callable[..., ModelForm]:
return InstitutionForm

def get(self, request, *args, **kwargs):
is_org_form = request and request.GET.get('institution_form_type') == 'org'
initial = {}
if is_org_form:
initial['is_organisation'] = TRUE_CHAR
if request and request.GET.get('from_suggestion', ''):
from_suggestion = request.GET.get('from_suggestion')
sug_values = InstitutionSuggestion(from_suggestion).initial_form_values()
if sug_values:
initial.update(sug_values)
form = self.form_factory(initial=initial)
return self.resp_form_page(request, form)



@login_required
def full_form(request, pk):
Expand Down
31 changes: 31 additions & 0 deletions location/location_suggestion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import dateutil.parser
import logging
from dateutil.parser import ParserError
from django.core.exceptions import ObjectDoesNotExist
from suggestions.models import CofkSuggestions
from suggestions import utils as sug_utils
from location import location_suggestion_fields

log = logging.getLogger(__name__)

class LocationSuggestion:
def __init__(self, suggestion_id):
self.suggestion_id = suggestion_id

def initial_form_values(self):
form_values = {}
try:
sug = CofkSuggestions.objects.get(pk=self.suggestion_id)
if sug.suggestion_status == "Resolved":
log.debug(f"{sug.suggestion_type} suggestion id {sug.suggestion_id} is already in status {sug.suggestion_status}")
return form_values
except ObjectDoesNotExist:
return form_values
parsed_suggestion = sug.parsed_suggestion
for field,sug_value in parsed_suggestion.items():
form_field = sug_utils.suggestion_fields_dict(location_suggestion_fields.suggestion_fields_map()).get(field, None)
if form_field and sug_value:
form_values[form_field] = sug_value
if form_values:
form_values['editors_notes'] = f"From suggestion {sug.suggestion_id}\n{sug.suggestion_suggestion}"
return form_values
12 changes: 12 additions & 0 deletions location/location_suggestion_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def suggestion_fields_map():
return (
("Full name of location", "location_name"),
("Alternative names of location", "location_synonyms"),
("Room", "element_1_eg_room"),
("Building", "element_2_eg_building"),
("Parish / District / Street", "element_3_eg_parish"),
("City / town / Village", "element_4_eg_city"),
("County", "element_5_eg_county"),
("Country", "element_6_eg_country"),
("Larger political entity", "element_7_eg_empire"),
)
18 changes: 18 additions & 0 deletions location/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
LocationImageRecrefAdapter
from location.subqueries import create_sql_count_work_by_location
from location.view_components import LocationFormDescriptor
from location.location_suggestion import LocationSuggestion
from suggestions import views as sug_view

log = logging.getLogger(__name__)
FormOrFormSet = Union[BaseForm, BaseFormSet]
Expand All @@ -57,12 +59,28 @@ def resp_form_page(self, request, form):
return render(request, 'location/init_form.html', {'loc_form': form})

def resp_after_saved(self, request, form, new_instance):
suggestion_id = request.GET.get('from_suggestion', None)
if suggestion_id:
sug_view.save_with_related_info(suggestion_id, new_instance.location_id)
return redirect('location:full_form', new_instance.location_id)

@property
def form_factory(self) -> Callable[..., BaseForm]:
return LocationForm

def get(self, request, *args, **kwargs):
is_org_form = request and request.GET.get('location_form_type') == 'org'
initial = {}
if is_org_form:
initial['is_organisation'] = TRUE_CHAR
if request and request.GET.get('from_suggestion', ''):
from_suggestion = request.GET.get('from_suggestion')
sug_values = LocationSuggestion(from_suggestion).initial_form_values()
if sug_values:
initial.update(sug_values)
form = self.form_factory(initial=initial)
return self.resp_form_page(request, form)


class LocationQuickInitView(LocationInitView):
def resp_after_saved(self, request, form, new_instance):
Expand Down
10 changes: 10 additions & 0 deletions login/templates/login/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ <h1> Welcome to EMLO Edit </h1>

</ul>

{% endif %}
{% if constant.PM_VIEW_SUGGESTIONS in perms %}
<p>You can also provide suggestions:</p>

<ul class="main_menu">
<li>
<a href="{% url 'suggestions:suggestion_all' %}" title="Make a suggestion" target="_self" tabindex="1"><span
data-feather="clipboard" class="feather-large" aria-hidden="true"></span>Suggestions</a>
</li>
</ul>
{% endif %}

{% if constant.PM_TRIGGER_EXPORTER|can_show_for_perm:perms %}
Expand Down
Loading