diff --git a/tigacrafting/migrations/0020_bookmark.py b/tigacrafting/migrations/0020_bookmark.py new file mode 100644 index 00000000..f1ec0f62 --- /dev/null +++ b/tigacrafting/migrations/0020_bookmark.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2.7 on 2024-10-09 12:09 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('tigaserver_app', '0047_merge_20240813_1025'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('tigacrafting', '0019_auto_20240122_1709'), + ] + + operations = [ + migrations.CreateModel( + name='BookMark', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.CharField(help_text='Label for the bookmark. It allows the user to quickly identify why a bookmark was put', max_length=150)), + ('module', models.CharField(help_text='Label which designates the module for which the bookmark is applied', max_length=150)), + ('report', models.ForeignKey(help_text='Report to which the bookmark was applied', on_delete=django.db.models.deletion.CASCADE, related_name='report_bookmarks', to='tigaserver_app.Report')), + ('user', models.ForeignKey(help_text='User which established the bookmark', on_delete=django.db.models.deletion.CASCADE, related_name='user_bookmarks', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'unique_together': {('user', 'report', 'label')}, + }, + ), + ] diff --git a/tigacrafting/migrations/0021_auto_20241009_1259.py b/tigacrafting/migrations/0021_auto_20241009_1259.py new file mode 100644 index 00000000..941d4d6b --- /dev/null +++ b/tigacrafting/migrations/0021_auto_20241009_1259.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.7 on 2024-10-09 12:59 + +from django.conf import settings +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('tigacrafting', '0020_bookmark'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='bookmark', + unique_together={('user', 'label')}, + ), + ] diff --git a/tigacrafting/migrations/0022_bookmark_json_filter.py b/tigacrafting/migrations/0022_bookmark_json_filter.py new file mode 100644 index 00000000..c2a2be5b --- /dev/null +++ b/tigacrafting/migrations/0022_bookmark_json_filter.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2024-10-10 10:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tigacrafting', '0021_auto_20241009_1259'), + ] + + operations = [ + migrations.AddField( + model_name='bookmark', + name='json_filter', + field=models.CharField(help_text='filter conditions when bookmark was set', max_length=500, null=True), + ), + ] diff --git a/tigacrafting/models.py b/tigacrafting/models.py index 5a2c41e0..b2cf2aa2 100644 --- a/tigacrafting/models.py +++ b/tigacrafting/models.py @@ -597,3 +597,13 @@ class Alert(models.Model): # species = models.ForeignKey(Species, related_name='validations', blank=True, null=True) # #species = models.ManyToManyField(Species) # validation_value = models.IntegerField('Validation Certainty', choices=VALIDATION_CATEGORIES, default=None, blank=True, null=True, help_text='Certainty value, 1 for probable, 2 for sure') + +class BookMark(models.Model): + user = models.ForeignKey(help_text='User which established the bookmark', to='auth.User', related_name='user_bookmarks', on_delete=models.CASCADE, ) + report = models.ForeignKey(help_text='Report to which the bookmark was applied', to='tigaserver_app.Report', related_name='report_bookmarks', on_delete=models.CASCADE, ) + label = models.CharField(help_text='Label for the bookmark. It allows the user to quickly identify why a bookmark was put', max_length=150) + module = models.CharField(help_text='Label which designates the module for which the bookmark is applied', max_length=150) + json_filter = models.CharField(help_text='filter conditions when bookmark was set', max_length=500, null=True) + + class Meta: + unique_together = ('user','label') diff --git a/tigacrafting/static/tigacrafting/javascript/coarse_filter.js b/tigacrafting/static/tigacrafting/javascript/coarse_filter.js index 1d38bf73..24d456d9 100644 --- a/tigacrafting/static/tigacrafting/javascript/coarse_filter.js +++ b/tigacrafting/static/tigacrafting/javascript/coarse_filter.js @@ -1,4 +1,12 @@ -const ask_confirmation = true; +const ask_confirmation = false; + +function escapeHtml(original_string) { + if(original_string == null){ + return null; + }else{ + return original_string.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); + } +} function make_site(report_id, type){ hide_adult_buttons(report_id); @@ -70,6 +78,33 @@ function hide_adult_buttons(report_id){ $(document).ready(function() { +function load_bookmarks(){ + $.ajax({ + url: '/api/bookmarks/', + type: "GET", + headers: { "X-CSRFToken": csrf_token }, + dataType: "json", + success: function(data) { + bookmarks = data; + init_bookmarks(); + }, + error: function(jqXHR, textStatus, errorThrown){ + //alert(jqXHR.responseJSON.message); + }, + cache: false + }); +} + +function init_bookmarks(){ + $('#bookmark_drawer').empty(); + const root = $('#bookmark_drawer'); + for(var i = 0; i < bookmarks.length; i++){ + const bookmark = bookmarks[i]; + const single_bookmark = single_bookmark_template(bookmark); + root.append(single_bookmark); + } +} + function type_shows_with_current_filter(type){ const filtered_type = $('#type_select').val(); if(filtered_type=='all'){ @@ -103,16 +138,43 @@ function reset_filter(){ $('#usernote_filter').val(''); } -function filter_to_ui(){ - const filter = ui_to_filter(); - const filter_json = JSON.parse(filter); - $('#visibility_filter').html(filter_json.visibility_readable); - $('#text_filter').html(filter_json.note); - $('#rtype_filter').html(filter_json.report_type_readable); - $('#country_filter').html(filter_json.country_readable); - $('#country_filter_exclude').html(filter_json.country_exclude_readable); - $('#ia_filter').html(filter_json.ia_threshold); - $('#usernote_filter').html(decodeURI(filter_json.note)); +function filter_to_ui(_filter){ + var filter_json; + if(_filter==null){ + const filter = ui_to_filter(); + filter_json = JSON.parse(filter); + }else{ + filter_json = JSON.parse(_filter); + } + $('#visibility_filter').html(escapeHtml(filter_json.visibility_readable)); + if( filter_json.visibility!= null && filter_json.visibility != '' ){ + $('#visibility_select option[value=' + filter_json.visibility + ']').prop('selected', true); + } + + $('#text_filter').html(escapeHtml(filter_json.note)); + $('#usernote_filter').val(filter_json.note); + + $('#rtype_filter').html(escapeHtml(filter_json.report_type_readable)); + if( filter_json.report_type!= null && filter_json.report_type != '' ){ + $('#type_select option[value=' + filter_json.report_type + ']').prop('selected', true); + } + + $('#country_filter').html(escapeHtml(filter_json.country_readable)); + if( filter_json.country!= null && filter_json.country != '' ){ + $('#country_select option[value=' + filter_json.country + ']').prop('selected', true); + } + + $('#country_filter_exclude').html(escapeHtml(filter_json.country_exclude_readable)); + if( filter_json.country_exclude!= null && filter_json.country_exclude != '' ){ + $('#country_select_exclude option[value=' + filter_json.country_exclude + ']').prop('selected', true); + } + + $('#ia_filter').html(escapeHtml(filter_json.ia_threshold)); + $("#slider").slider('value',filter_json.ia_threshold); + $( "#slider_value" ).html(escapeHtml(filter_json.ia_threshold)); + + $('#usernote_filter').html(escapeHtml(decodeURI(filter_json.note))); + $('#usernote_filter').val(filter_json.note); } function ui_to_filter(){ @@ -287,6 +349,7 @@ function classify_picture(report_id, category_id, validation_value){ success: function(data) { $('#' + report_id).unblock(); remove_report(report_id); + load_bookmarks(); }, error: function(jqXHR, textStatus, errorThrown){ if( jqXHR.responseJSON.opcode == -1 ){ @@ -310,6 +373,7 @@ function quick_upload_report(report_id){ success: function(data) { $('#' + report_id).unblock(); remove_report(report_id); + load_bookmarks(); }, error: function(jqXHR, textStatus, errorThrown){ if( jqXHR.responseJSON.opcode == -1 ){ @@ -359,10 +423,10 @@ function flip_report(report_id, flip_to_type, flip_to_subtype){ }); } -function load_data(limit=300, offset=1, q=''){ +function load_data(limit=300, offset=1, q='', seek=''){ lockui(); $.ajax({ - url: `/api/coarse_filter_reports/?limit=${limit}&offset=${offset}&q=${q}`, + url: `/api/coarse_filter_reports/?limit=${limit}&offset=${offset}&q=${q}&seek=${seek}`, type: "GET", dataType: "json", success: function(data) { @@ -387,6 +451,14 @@ function load_data(limit=300, offset=1, q=''){ init_maps(); load_previews(); set_visibility_icons(); + if(seek!=''){ + const report_bkm = $('#bkm_' + seek).data('report'); + $("#" + report_bkm).get(0).scrollIntoView(); + const filter = data.filter; + filter_to_ui(filter); + } + set_bookmarks(); + init_bookmarks(); }, error: function(jqXHR, textStatus, errorThrown){ unlockui(); @@ -413,6 +485,30 @@ function pictures_template(pictures){ return elements; } +function single_bookmark_template(bookmark){ + return ` + + ` +} + +function add_ui_bookmark(bookmark){ + const root = $('#bookmark_drawer'); + const single_bookmark = single_bookmark_template(bookmark); + root.append(single_bookmark); + bookmarks.push(bookmark); +} + +function remove_ui_bookmark(id){ + $('#bkm_' + id).remove(); + var new_bookmarks = []; + for(var i = 0; i < bookmarks.length; i++){ + if(bookmarks[i].id != id){ + new_bookmarks.push(bookmarks[i]) + } + } + bookmarks = new_bookmarks; +} + function single_report_template(report){ const pictures = pictures_template(report.photos); const report_country_name = report.country == null ? 'No country' : report.country.name_engl; @@ -434,6 +530,7 @@ function single_report_template(report){ } return `