summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2020-03-11 13:27:04 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2020-03-11 13:27:04 +0100
commit3fd126b25be6a50c49b4525941d216fa92f727b0 (patch)
treec248b4e8b129d017373af2a07d399f5ca82717b1
parent9429df335283ff6de8c0e21778bb0e7fbda6b149 (diff)
downloadIshtar-3fd126b25be6a50c49b4525941d216fa92f727b0.tar.bz2
Ishtar-3fd126b25be6a50c49b4525941d216fa92f727b0.zip
Searc criteria: add has image/file/url criteria for all document items
-rw-r--r--CHANGES.md10
-rw-r--r--archaeological_context_records/forms.py4
-rw-r--r--archaeological_context_records/models.py6
-rw-r--r--archaeological_files/forms.py6
-rw-r--r--archaeological_files/models.py7
-rw-r--r--archaeological_finds/forms.py15
-rw-r--r--archaeological_finds/forms_treatments.py9
-rw-r--r--archaeological_finds/models_finds.py9
-rw-r--r--archaeological_finds/models_treatments.py17
-rw-r--r--archaeological_operations/forms.py6
-rw-r--r--archaeological_operations/models.py13
-rw-r--r--archaeological_warehouse/forms.py4
-rw-r--r--archaeological_warehouse/models.py6
-rw-r--r--ishtar_common/forms.py24
-rw-r--r--ishtar_common/models.py17
15 files changed, 115 insertions, 38 deletions
diff --git a/CHANGES.md b/CHANGES.md
index b3907be7f..821d79c04 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,7 +1,7 @@
Ishtar changelog
================
-v3.0.4 - 2020-XX-XX
+v3.0.4 - 2020-03-11
-------------------
### Features ###
- Quick actions - sheets: add duplicate for site, operation, document and context record
@@ -17,6 +17,14 @@ v3.0.4 - 2020-XX-XX
- operation: town, scientist
- Warehouse:
- town
+ - All document items:
+ - has associated file
+ - has associated image
+ - has associated url
+
+### Bug fixes ###
+- Tables: fix display of links in columns
+- Criteria search: manage empty field (but not NULL) multiple level search for file (including images) fields
v3.0.3 - 2020-02-24
diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py
index 87cad2c66..5ed9935e9 100644
--- a/archaeological_context_records/forms.py
+++ b/archaeological_context_records/forms.py
@@ -35,7 +35,7 @@ from archaeological_context_records import models
from ishtar_common.forms import FinalForm, FormSet, \
reverse_lazy, get_form_selection, ManageOldType, CustomForm, \
FieldType, CustomFormSearch, IshtarForm, FormHeader, HistorySelect, \
- MultiSearchForm, LockForm
+ MultiSearchForm, LockForm, DocumentItemSelect
from ishtar_common.forms_common import get_town_field
from archaeological_operations.forms import OperationSelect, ParcelField, \
RecordRelationsForm as OpeRecordRelationsForm, RecordRelationsFormSetBase
@@ -60,7 +60,7 @@ class OperationFormSelection(CustomForm, forms.Form):
validators=[valid_id(Operation)])
-class RecordSelect(HistorySelect):
+class RecordSelect(DocumentItemSelect):
_model = models.ContextRecord
form_admin_name = _(u"Context record - 001 - Search")
form_slug = "contextrecord-001-search"
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index 9b1483e0d..02b074706 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -362,6 +362,11 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem,
'operation_id': 'operation_id',
'unit__label': "unit__label"
}
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
RELATION_TYPES_PREFIX = {'ope_relation_types': 'operation__',
'cr_relation_types': ''}
# alternative names of fields for searches
@@ -416,6 +421,7 @@ class ContextRecord(BulkUpdatedItem, DocumentItem, BaseHistorizedItem,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
PARENT_ONLY_SEARCH_VECTORS = ["operation", "archaeological_site", "parcel"]
BASE_SEARCH_VECTORS = [
diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py
index 9a2f63a1d..a9936c47a 100644
--- a/archaeological_files/forms.py
+++ b/archaeological_files/forms.py
@@ -37,8 +37,8 @@ from archaeological_operations.models import ActType, AdministrativeAct, \
from . import models
from ishtar_common.forms import FinalForm, get_now, reverse_lazy, TableSelect, \
- ManageOldType, CustomForm, FieldType, IshtarForm, HistorySelect, \
- MultiSearchForm, LockForm, CustomFormSearch
+ ManageOldType, CustomForm, FieldType, IshtarForm, \
+ MultiSearchForm, LockForm, CustomFormSearch, DocumentItemSelect
from ishtar_common.forms_common import get_town_field
from archaeological_operations.forms import AdministrativeActForm, \
AdministrativeActOpeFormSelection, SLICING, AdministrativeActModifForm, \
@@ -47,7 +47,7 @@ from ishtar_common import widgets
from bootstrap_datepicker.widgets import DatePicker
-class FileSelect(HistorySelect):
+class FileSelect(DocumentItemSelect):
_model = models.File
form_admin_name = _(u"File - 001 - Search")
form_slug = "file-001-search"
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index 018b5d429..310301c59 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -161,6 +161,12 @@ class File(ClosedItem, DocumentItem, BaseHistorizedItem, OwnPerms, ValueGetter,
'towns_label': _(u"Towns"),
}
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
+
# alternative names of fields for searches
ALT_NAMES = {
'year': SearchAltName(
@@ -230,6 +236,7 @@ class File(ClosedItem, DocumentItem, BaseHistorizedItem, OwnPerms, ValueGetter,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
POST_PROCESS_REQUEST = {
'towns__numero_insee__startswith': '_get_department_code',
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py
index 316253a7a..90805e656 100644
--- a/archaeological_finds/forms.py
+++ b/archaeological_finds/forms.py
@@ -56,7 +56,7 @@ from ishtar_common import widgets
from ishtar_common.forms import CustomForm, CustomFormSearch, FormSet, \
FloatField, reverse_lazy, TableSelect, get_now, FinalForm, \
ManageOldType, FieldType, IshtarForm, FormHeader, QAForm, HistorySelect, \
- MultiSearchForm, LockForm
+ MultiSearchForm, LockForm, DocumentItemSelect
from ishtar_common.forms_common import get_town_field
from ishtar_common.models import valid_id, valid_ids, get_current_profile, \
SpatialReferenceSystem, Area, OperationType, IshtarUser
@@ -524,8 +524,8 @@ class ResultingFindsForm(CustomForm, ManageOldType):
label=_(u"Prefix label for resulting finds"),
validators=[validators.MaxLengthValidator(200)],
help_text=_(
- u'E.g.: with a prefix "item-", each resulting item will be named '
- u'"item-1", "item-2", "item-3"')
+ 'E.g.: with a prefix "item-", each resulting item will be named '
+ '"item-1", "item-2", "item-3"')
)
resultings_start_number = forms.IntegerField(
label=_(u"Numbering starting from"), initial=1, min_value=0
@@ -908,9 +908,9 @@ DatingFormSet.form_admin_name = _(u"Find - 040 - Dating")
DatingFormSet.form_slug = "find-040-dating"
-class FindSelect(HistorySelect):
+class FindSelect(DocumentItemSelect):
_model = models.Find
- form_admin_name = _(u"Find - 001 - Search")
+ form_admin_name = _("Find - 001 - Search")
form_slug = "find-001-search"
FORM_FILTERS = [
(_(u"Find origin"), [
@@ -1051,9 +1051,9 @@ class FindSelect(HistorySelect):
reverse_lazy('autocomplete-materialtype'),
associated_model=models.MaterialType),
)
- material_type_quality = forms.ChoiceField(label=_(u"Material type quality"),
+ material_type_quality = forms.ChoiceField(label=_("Material type quality"),
choices=[])
- material_comment = forms.CharField(label=_(u"Comment on the material"))
+ material_comment = forms.CharField(label=_("Comment on the material"))
object_types = forms.IntegerField(
label=_(u"Object type"),
widget=widgets.JQueryAutoComplete(
@@ -1182,7 +1182,6 @@ class FindSelect(HistorySelect):
appraisal_date__before = forms.DateField(
label=_(u"Appraisal date before"), widget=DatePicker)
- documents__image__isnull = forms.NullBooleanField(label=_(u"Has an image?"))
loan = forms.NullBooleanField(label=_(u"Loan?"))
treatments_file_end_date = forms.DateField(
label=_(u"Treatment file end date before"), widget=DatePicker
diff --git a/archaeological_finds/forms_treatments.py b/archaeological_finds/forms_treatments.py
index f03dec18a..b80b6c0fe 100644
--- a/archaeological_finds/forms_treatments.py
+++ b/archaeological_finds/forms_treatments.py
@@ -33,8 +33,8 @@ from archaeological_warehouse.models import Warehouse, Container
from bootstrap_datepicker.widgets import DatePicker
from ishtar_common import widgets
from ishtar_common.forms import reverse_lazy, TableSelect, FinalForm, \
- ManageOldType, CustomForm, FieldType, IshtarForm, HistorySelect, \
- MultiSearchForm
+ ManageOldType, CustomForm, FieldType, IshtarForm, \
+ DocumentItemSelect, MultiSearchForm
from ishtar_common.models import Person, valid_id, valid_ids, Organization, \
get_current_profile
@@ -43,7 +43,7 @@ logger = logging.getLogger(__name__)
# Treatment
-class TreatmentSelect(HistorySelect):
+class TreatmentSelect(DocumentItemSelect):
_model = models.Treatment
form_admin_name = _(u"Treatment - 001 - Search")
form_slug = "treatment-001-search"
@@ -63,7 +63,6 @@ class TreatmentSelect(HistorySelect):
associated_model=Person),
label=_(u"Scientific monitoring manager"))
treatment_types = forms.ChoiceField(label=_(u"Treatment type"), choices=[])
- documents__image__isnull = forms.NullBooleanField(label=_(u"Has an image?"))
def __init__(self, *args, **kwargs):
super(TreatmentSelect, self).__init__(*args, **kwargs)
@@ -662,7 +661,7 @@ class AdministrativeActTreatmentModifForm(
# treatment requests
-class TreatmentFileSelect(HistorySelect):
+class TreatmentFileSelect(DocumentItemSelect):
_model = models.TreatmentFile
form_admin_name = _(u"Treatment file - 001 - Search")
form_slug = "treatmentfile-001-search"
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index ad5c803fa..328821386 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -880,7 +880,9 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,
)
# search parameters
- REVERSED_BOOL_FIELDS = ['documents__image__isnull']
+ REVERSED_BOOL_FIELDS = ['documents__image__isnull',
+ 'documents__associated_url__isnull',
+ 'documents__associated_file__isnull']
BOOL_FIELDS = ['is_complete']
RELATION_TYPES_PREFIX = {
'ope_relation_types':
@@ -1042,10 +1044,6 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,
SearchAltName(
pgettext_lazy("key for text search", "checked"),
'checked_type__label__iexact'),
- 'documents__image__isnull':
- SearchAltName(
- pgettext_lazy("key for text search", "has-image"),
- 'documents__image__isnull'),
'container_ref__location':
SearchAltName(
pgettext_lazy("key for text search", "location"),
@@ -1364,6 +1362,7 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
DYNAMIC_REQUESTS = {
'current_division': DynamicRequest(
diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py
index a8a06ae27..071d80af1 100644
--- a/archaeological_finds/models_treatments.py
+++ b/archaeological_finds/models_treatments.py
@@ -74,7 +74,11 @@ class Treatment(DashboardFormItem, ValueGetter, DocumentItem,
'person__cached_label',
'start_date', 'downstream_cached_label',
'upstream_cached_label')
- REVERSED_BOOL_FIELDS = ['documents__image__isnull']
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
EXTRA_REQUEST_KEYS = {
"downstream_cached_label": "downstream__cached_label",
"upstream_cached_label": "upstream__cached_label",
@@ -115,10 +119,6 @@ class Treatment(DashboardFormItem, ValueGetter, DocumentItem,
pgettext_lazy("key for text search", "index"),
'index'
),
- 'documents__image__isnull': SearchAltName(
- pgettext_lazy("key for text search", "has-image"),
- 'documents__image__isnull'
- ),
'treatment_types': SearchAltName(
pgettext_lazy("key for text search", "type"),
'treatment_types__label__iexact'
@@ -129,6 +129,7 @@ class Treatment(DashboardFormItem, ValueGetter, DocumentItem,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
HISTORICAL_M2M = [
'treatment_types',
]
@@ -914,6 +915,11 @@ class TreatmentFile(DashboardFormItem, ClosedItem, DocumentItem,
"in_charge__pk": "in_charge__pk", # used by dynamic_table_documents
"applicant__pk": "applicant__pk", # used by dynamic_table_documents
}
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
# alternative names of fields for searches
ALT_NAMES = {
'name': SearchAltName(
@@ -966,6 +972,7 @@ class TreatmentFile(DashboardFormItem, ClosedItem, DocumentItem,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
DATED_FIELDS = ['exhibition_start_date__lte',
'exhibition_start_date__gte',
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index 9a3335df5..d665fc779 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -41,7 +41,7 @@ from ishtar_common import widgets
from ishtar_common.forms import FinalForm, FormSet, get_now, \
reverse_lazy, TableSelect, get_data_from_formset, QAForm, CustomFormSearch,\
ManageOldType, IshtarForm, CustomForm, FieldType, FormHeader, \
- HistorySelect, LockForm, MultiSearchForm
+ DocumentItemSelect, LockForm, MultiSearchForm
from ishtar_common.forms_common import TownFormSet, get_town_field, TownForm
from ishtar_common.models import valid_id, valid_ids, Person, Town, \
DocumentTemplate, Organization, get_current_profile, \
@@ -472,7 +472,7 @@ RecordRelationsFormSet.form_admin_name = _(u"Operation - 080 - Relations")
RecordRelationsFormSet.form_slug = "operation-080-relations"
-class OperationSelect(HistorySelect):
+class OperationSelect(DocumentItemSelect):
_model = models.Operation
form_admin_name = _(u"Operation - 001 - Search")
form_slug = "operation-001-search"
@@ -1367,7 +1367,7 @@ class OperationDeletionForm(FinalForm):
#########
-class SiteSelect(HistorySelect):
+class SiteSelect(DocumentItemSelect):
_model = models.ArchaeologicalSite
form_admin_name = _(u"Archaeological site - 001 - Search")
form_slug = "archaeological_site-001-search"
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 8dd6568b8..8a415c0c5 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -180,6 +180,11 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
}
# alternative names of fields for searches
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
ALT_NAMES = {
'reference': SearchAltName(
pgettext_lazy("key for text search", "reference"),
@@ -264,6 +269,7 @@ class ArchaeologicalSite(DocumentItem, BaseHistorizedItem, QRCodeItem,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
UP_MODEL_QUERY = {
"operation": (pgettext_lazy("key for text search", "operation"),
@@ -694,6 +700,11 @@ class Operation(ClosedItem, DocumentItem, BaseHistorizedItem, QRCodeItem,
# search parameters
BOOL_FIELDS = ['end_date__isnull', 'virtual_operation',
'documentation_received', 'finds_received']
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
DATED_FIELDS = [
'start_date__lte', 'start_date__gte', 'excavation_end_date__lte',
'excavation_end_date__gte', 'documentation_deadline__lte',
@@ -951,6 +962,8 @@ class Operation(ClosedItem, DocumentItem, BaseHistorizedItem, QRCodeItem,
),
}
ALT_NAMES.update(BaseHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
+
QA_EDIT = QuickAction(
url="operation-qa-bulk-update", icon_class="fa fa-pencil",
text=_(u"Bulk update"), target="many",
diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py
index 867761047..a7b6c575e 100644
--- a/archaeological_warehouse/forms.py
+++ b/archaeological_warehouse/forms.py
@@ -42,7 +42,7 @@ from bootstrap_datepicker.widgets import DatePicker
from ishtar_common.forms import name_validator, reverse_lazy, \
get_form_selection, ManageOldType, FinalForm, FormSet, \
- CustomForm, FieldType, HistorySelect, FormHeader, TableSelect, \
+ CustomForm, FieldType, DocumentItemSelect, FormHeader, TableSelect, \
CustomFormSearch, MultiSearchForm, LockForm
from ishtar_common.forms_common import get_town_field
from archaeological_finds.forms import FindMultipleFormSelection, \
@@ -354,7 +354,7 @@ class ContainerModifyForm(ContainerForm):
return cleaned_data
-class ContainerSelect(HistorySelect):
+class ContainerSelect(DocumentItemSelect):
_model = models.Container
form_admin_name = _(u"Container - 001 - Search")
form_slug = "container-001-search"
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index 325adce9e..63d4497ac 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -603,9 +603,15 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem,
),
}
+ REVERSED_BOOL_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ ]
REVERSED_MANY_COUNTED_FIELDS = ['finds', 'finds_ref']
ALT_NAMES.update(LightHistorizedItem.ALT_NAMES)
+ ALT_NAMES.update(DocumentItem.ALT_NAMES)
DYNAMIC_REQUESTS = {
'division': DynamicRequest(
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index 17ada982f..939563334 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -782,23 +782,39 @@ class HistorySelect(CustomForm, TableSelect):
label=_("Modified after"), widget=DatePicker,
required=False)
_explicit_ordering = True
+ CURRENT_FIELDS = ["history_creator", "history_modifier",
+ "modified_before", "modified_after"]
def __init__(self, *args, **kwargs):
super(HistorySelect, self).__init__(*args, **kwargs)
field_order = self.fields.keys()
- current_fields = ["history_creator", "history_modifier",
- "modified_before", "modified_after"]
fields = OrderedDict()
for k in field_order:
- if k in current_fields:
+ if k in self.CURRENT_FIELDS:
continue
fields[k] = self.fields[k]
- for k in current_fields:
+ for k in self.CURRENT_FIELDS:
fields[k] = self.fields[k]
self.fields = fields
self.custom_form_ordering()
+class DocumentItemSelect(HistorySelect):
+ documents__image__isnull = forms.NullBooleanField(label=_("Has an image?"))
+ documents__associated_file__isnull = forms.NullBooleanField(
+ label=_("Has an attached file?"))
+ documents__associated_url__isnull = forms.NullBooleanField(
+ label=_("Has a web address?"))
+ CURRENT_FIELDS = [
+ 'documents__image__isnull',
+ 'documents__associated_file__isnull',
+ 'documents__associated_url__isnull',
+ "history_creator", "history_modifier",
+ "modified_before", "modified_after"
+ ]
+ _explicit_ordering = True
+
+
def get_now():
format = formats.get_format('DATE_INPUT_FORMATS')[0]
value = datetime.datetime.now().strftime(format)
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index dc2fef815..5fa668faf 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -1818,6 +1818,21 @@ class QRCodeItem(models.Model, ImageContainerModel):
class DocumentItem(object):
+ ALT_NAMES = {
+ 'documents__image__isnull':
+ SearchAltName(
+ pgettext_lazy("key for text search", "has-image"),
+ 'documents__image__isnull'),
+ 'documents__associated_url__isnull':
+ SearchAltName(
+ pgettext_lazy("key for text search", "has-url"),
+ 'documents__associated_url__isnull'),
+ 'documents__associated_file__isnull':
+ SearchAltName(
+ pgettext_lazy("key for text search", "has-attached-file"),
+ 'documents__associated_file__isnull'),
+ }
+
def public_representation(self):
images = []
if getattr(self, "main_image", None):
@@ -5600,6 +5615,8 @@ class Document(BaseHistorizedItem, QRCodeItem, OwnPerms, ImageModel,
no_path_change = 'no_path_change' in kwargs \
and kwargs.pop('no_path_change')
self.set_index()
+ if not self.associated_url:
+ self.associated_url = None
super(Document, self).save(*args, **kwargs)
if self.image and not no_path_change and \