From 6288294b1e4b0673376165d67935f04a2f4a755f Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:00:19 +0200 Subject: [PATCH 01/28] enable italicisation of portion --- indigo_api/views/documents.py | 26 ++++++++++++++++++- .../indigo/views/document_italics_terms.js | 12 ++++++--- .../indigo_api/document/_toolbar.html | 2 +- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/indigo_api/views/documents.py b/indigo_api/views/documents.py index 831038d87..a018a2a98 100644 --- a/indigo_api/views/documents.py +++ b/indigo_api/views/documents.py @@ -14,6 +14,7 @@ from django.utils.translation import gettext as _ from django_comments.models import Comment +from lxml import etree from rest_framework.exceptions import ValidationError, MethodNotAllowed from rest_framework.views import APIView from rest_framework import mixins, viewsets, renderers, status @@ -404,15 +405,38 @@ class MarkUpItalicsTermsView(DocumentResourceView, APIView): """ Find and mark up italics terms. """ def post(self, request, document_id): - serializer = DocumentAPISerializer(instance=self.document, data=self.request.data) + # in provision mode, fake a full e.g. using the portion XML + data = self.request.data + provision_eid = data['document'].pop('provision_eid', None) + if provision_eid: + data['document']['content'] = self.switch_doctype(data['document']['content'], self.document.work.work_uri.doctype) + + serializer = DocumentAPISerializer(instance=self.document, data=data) serializer.fields['document'].fields['content'].required = True serializer.is_valid(raise_exception=True) document = serializer.fields['document'].update_document(self.document, serializer.validated_data['document']) self.mark_up_italics(document) + # in provision mode, turn the fake full document back into a portion, minus the wrapping akn tag + if provision_eid: + document.document_xml = self.switch_doctype(document.document_xml, self.document.work.work_uri.doctype, back_to_portion=True) + return Response({'document': {'content': document.document_xml}}) + def switch_doctype(self, xml, doctype, back_to_portion=False): + old_doc = StructuredDocument.for_document_type(doctype if back_to_portion else 'portion')(xml) + new_doc = StructuredDocument.for_document_type('portion' if back_to_portion else doctype)() + # delete any empty section in body, for example + for blank in new_doc.main_content.xpath('*'): + new_doc.main_content.remove(blank) + for elem in old_doc.main_content.xpath('*'): + new_doc.main_content.append(elem) + if back_to_portion: + # no wrapping akn tag in provision mode + return etree.tostring(new_doc.main, encoding='unicode') + return etree.tostring(new_doc.root, encoding='unicode') + def mark_up_italics(self, document): italics_terms_finder = plugins.for_document('italics-terms', document) italics_terms = document.work.country.italics_terms diff --git a/indigo_app/static/javascript/indigo/views/document_italics_terms.js b/indigo_app/static/javascript/indigo/views/document_italics_terms.js index eb1ac96f8..a1b2a2b27 100644 --- a/indigo_app/static/javascript/indigo/views/document_italics_terms.js +++ b/indigo_app/static/javascript/indigo/views/document_italics_terms.js @@ -40,7 +40,12 @@ $btn = this.$el.find('.mark-up-italics'), data = {'document': this.model.document.toJSON()}; - data.document.content = this.model.toXml(); + let content = this.model.toXml(); + if (Indigo.Preloads.provisionEid) { + content = `${content}`; + data.document.provision_eid = Indigo.Preloads.provisionEid; + } + data.document.content = content; this.$('a[href="#this-document-italics-terms"]').click(); @@ -66,9 +71,9 @@ removeItalics: function(e) { // remove all italics mark-up - var self = this, - changed = false; + let changed = false; + // TODO: navigate to 'In this document' first (this click() doesn't do anything) this.$('a[href="#this-document-italics-terms"]').click(); this.model.xmlDocument.querySelectorAll('i').forEach(function(term) { @@ -82,7 +87,6 @@ if (changed) { this.model.trigger('change:dom'); - // TODO: refresh content without saving } } }); diff --git a/indigo_app/templates/indigo_api/document/_toolbar.html b/indigo_app/templates/indigo_api/document/_toolbar.html index 2faa82e90..f943d1cbd 100644 --- a/indigo_app/templates/indigo_api/document/_toolbar.html +++ b/indigo_app/templates/indigo_api/document/_toolbar.html @@ -35,7 +35,7 @@ {% trans "References..." %} - {% trans "Italicised terms..." %} From a2e64fc382ed386a289147920aa0cb5705de5ced Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:28:12 +0200 Subject: [PATCH 02/28] include portionBody in TextPatternMarker'a ancestor elements --- indigo/analysis/markup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indigo/analysis/markup.py b/indigo/analysis/markup.py index e01791e94..56df08741 100644 --- a/indigo/analysis/markup.py +++ b/indigo/analysis/markup.py @@ -16,7 +16,7 @@ class TextPatternMarker: """ Xpath for candidate text nodes that should be tested for matches. Must be defined by subclasses. """ - ancestors = ['coverpage', 'preface', 'preamble', 'body', 'mainBody', 'conclusions'] + ancestors = ['coverpage', 'preface', 'preamble', 'body', 'mainBody', 'portionBody', 'conclusions'] """ Tags that the candidate_xpath should be run against. """ From 7e44d4c9c0f33b5336cecb4a341b7a1d4e25798b Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:42:15 +0200 Subject: [PATCH 03/28] new DocumentAPISerializer --- indigo_api/serializers.py | 50 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/indigo_api/serializers.py b/indigo_api/serializers.py index 340c1ce6a..c2d3a7ffd 100644 --- a/indigo_api/serializers.py +++ b/indigo_api/serializers.py @@ -1,26 +1,24 @@ -import logging import os.path -from itertools import groupby -from typing import List - -from actstream.signals import action from collections import OrderedDict -from lxml.etree import LxmlError - -from django.contrib.auth.models import User +import logging +import reversion +from actstream.signals import action +from allauth.account.utils import user_display from django.conf import settings +from django.contrib.auth.models import User +from lxml import etree +from lxml.etree import LxmlError from rest_framework import serializers -from rest_framework.reverse import reverse from rest_framework.exceptions import ValidationError -from cobalt import StructuredDocument, FrbrUri -from cobalt.akn import AKN_NAMESPACES, DEFAULT_VERSION -import reversion +from rest_framework.reverse import reverse +from typing import List +from cobalt import StructuredDocument, FrbrUri +from cobalt.akn import AKN_NAMESPACES from indigo_api.models import Document, Attachment, Annotation, DocumentActivity, Work, Amendment, Language, \ PublicationDocument, Task, Commencement from indigo_api.signals import document_published -from allauth.account.utils import user_display log = logging.getLogger(__name__) @@ -438,11 +436,29 @@ class DocumentAPISerializer(serializers.Serializer): """ Helper to handle input documents for general document APIs """ - document = DocumentSerializer(required=True) + xml = serializers.CharField() + language = serializers.CharField(min_length=3, max_length=3) + is_portion = serializers.BooleanField() + + def update_document(self, document): + # the language could have been changed but not yet saved during editing, which might affect which plugin is used + if document.language.code != self.validated_data.get('language'): + document.language = Language.for_code(self.validated_data.get('language')) + # the FRBR URI doctype needs to match the XML root's child; change it to portion in provision mode + if self.validated_data.get('is_portion'): + document.work.work_uri.doctype = 'portion' + document.content = self.validated_data.get('xml') + return document - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.fields['document'].instance = self.instance + def updated_xml(self, document): + xml = document.document_xml + # in provision mode, unwrap the akn tag as we don't want the 'Entire document' option for editing + if self.validated_data.get('is_portion'): + root = etree.fromstring(xml) + # akn will always have exactly one child, 'portion' + portion = root.xpath('a:portion', namespaces={'a': document.doc.namespace})[0] + xml = etree.tostring(portion, encoding='unicode') + return xml class NoopSerializer(object): From 4c702f79ffa8b6f032385cd77dd23f86e09b5b8d Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:23:54 +0200 Subject: [PATCH 04/28] validate XML, improve updated_xml() --- indigo_api/serializers.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/indigo_api/serializers.py b/indigo_api/serializers.py index c2d3a7ffd..b6593e07c 100644 --- a/indigo_api/serializers.py +++ b/indigo_api/serializers.py @@ -15,7 +15,7 @@ from typing import List from cobalt import StructuredDocument, FrbrUri -from cobalt.akn import AKN_NAMESPACES +from cobalt.akn import AKN_NAMESPACES, DEFAULT_VERSION from indigo_api.models import Document, Attachment, Annotation, DocumentActivity, Work, Amendment, Language, \ PublicationDocument, Task, Commencement from indigo_api.signals import document_published @@ -440,7 +440,22 @@ class DocumentAPISerializer(serializers.Serializer): language = serializers.CharField(min_length=3, max_length=3) is_portion = serializers.BooleanField() - def update_document(self, document): + def validate_xml(self, xml): + """ mostly copied from DocumentSerializer.validate() + """ + try: + doctype = self.instance.work_uri.doctype if not self.initial_data.get('is_portion') else 'portion' + doc = StructuredDocument.for_document_type(doctype)(xml) + except (LxmlError, ValueError) as e: + raise ValidationError("Invalid XML: %s" % str(e)) + # ensure the correct namespace + if doc.namespace != AKN_NAMESPACES[DEFAULT_VERSION]: + raise ValidationError( + f"Document must have namespace {AKN_NAMESPACES[DEFAULT_VERSION]}, but it has {doc.namespace} instead.") + return xml + + def update_document(self): + document = self.instance # the language could have been changed but not yet saved during editing, which might affect which plugin is used if document.language.code != self.validated_data.get('language'): document.language = Language.for_code(self.validated_data.get('language')) @@ -450,15 +465,11 @@ def update_document(self, document): document.content = self.validated_data.get('xml') return document - def updated_xml(self, document): - xml = document.document_xml + def updated_xml(self): # in provision mode, unwrap the akn tag as we don't want the 'Entire document' option for editing if self.validated_data.get('is_portion'): - root = etree.fromstring(xml) - # akn will always have exactly one child, 'portion' - portion = root.xpath('a:portion', namespaces={'a': document.doc.namespace})[0] - xml = etree.tostring(portion, encoding='unicode') - return xml + return etree.tostring(self.instance.doc.portion, encoding='unicode') + return self.instance.document_xml class NoopSerializer(object): From f9345adef6df1339fd1e89938e61125134cabfaf Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:26:16 +0200 Subject: [PATCH 05/28] update MarkUpItalicsTermsView to use new serializer --- indigo_api/views/documents.py | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/indigo_api/views/documents.py b/indigo_api/views/documents.py index a018a2a98..fad4aa930 100644 --- a/indigo_api/views/documents.py +++ b/indigo_api/views/documents.py @@ -14,7 +14,6 @@ from django.utils.translation import gettext as _ from django_comments.models import Comment -from lxml import etree from rest_framework.exceptions import ValidationError, MethodNotAllowed from rest_framework.views import APIView from rest_framework import mixins, viewsets, renderers, status @@ -31,7 +30,7 @@ from indigo.analysis.refs.base import markup_document_refs from indigo.plugins import plugins from indigo.xmlutils import parse_html_str -from ..models import Document, Annotation, DocumentActivity, Task +from ..models import Document, Annotation, DocumentActivity, Task, Language, Work from ..serializers import DocumentSerializer, RenderSerializer, ParseSerializer, DocumentAPISerializer, VersionSerializer, AnnotationSerializer, DocumentActivitySerializer, TaskSerializer, DocumentDiffSerializer from ..renderers import AkomaNtosoRenderer, PDFRenderer, EPUBRenderer, HTMLRenderer, ZIPRenderer from indigo_api.exporters import HTMLExporter @@ -405,37 +404,11 @@ class MarkUpItalicsTermsView(DocumentResourceView, APIView): """ Find and mark up italics terms. """ def post(self, request, document_id): - # in provision mode, fake a full e.g. using the portion XML - data = self.request.data - provision_eid = data['document'].pop('provision_eid', None) - if provision_eid: - data['document']['content'] = self.switch_doctype(data['document']['content'], self.document.work.work_uri.doctype) - - serializer = DocumentAPISerializer(instance=self.document, data=data) - serializer.fields['document'].fields['content'].required = True + serializer = DocumentAPISerializer(instance=self.document, data=self.request.data) serializer.is_valid(raise_exception=True) - document = serializer.fields['document'].update_document(self.document, serializer.validated_data['document']) - + document = serializer.update_document() self.mark_up_italics(document) - - # in provision mode, turn the fake full document back into a portion, minus the wrapping akn tag - if provision_eid: - document.document_xml = self.switch_doctype(document.document_xml, self.document.work.work_uri.doctype, back_to_portion=True) - - return Response({'document': {'content': document.document_xml}}) - - def switch_doctype(self, xml, doctype, back_to_portion=False): - old_doc = StructuredDocument.for_document_type(doctype if back_to_portion else 'portion')(xml) - new_doc = StructuredDocument.for_document_type('portion' if back_to_portion else doctype)() - # delete any empty section in body, for example - for blank in new_doc.main_content.xpath('*'): - new_doc.main_content.remove(blank) - for elem in old_doc.main_content.xpath('*'): - new_doc.main_content.append(elem) - if back_to_portion: - # no wrapping akn tag in provision mode - return etree.tostring(new_doc.main, encoding='unicode') - return etree.tostring(new_doc.root, encoding='unicode') + return Response({'xml': serializer.updated_xml()}) def mark_up_italics(self, document): italics_terms_finder = plugins.for_document('italics-terms', document) From 3a24517a2d04afb12fc3979466a455d937bcc31a Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:28:43 +0200 Subject: [PATCH 06/28] add and use wrapInAkn, toSimplifiedJSON to DocumentContent --- indigo_app/static/javascript/indigo/models.js | 23 +++++++++++++++---- .../indigo/views/document_italics_terms.js | 13 +++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/indigo_app/static/javascript/indigo/models.js b/indigo_app/static/javascript/indigo/models.js index 74be22db0..35855d3ff 100644 --- a/indigo_app/static/javascript/indigo/models.js +++ b/indigo_app/static/javascript/indigo/models.js @@ -73,6 +73,23 @@ return Indigo.toXml(node || this.xmlDocument); }, + // in provision mode, wrap serialized XML in akn tags + wrapInAkn: function (xml) { + if (Indigo.Preloads.provisionEid) { + xml = `${xml}`; + } + return xml; + }, + + // serialise the absolute basics of the document for server-side XML manipulation + toSimplifiedJSON: function() { + return { + "xml": this.wrapInAkn(this.toXml()), + "language": this.document.attributes.language, + "is_portion": Indigo.Preloads.provisionEid !== "" + }; + }, + /** * Replaces (or deletes) an existing node (or the whole tree) with a new node or nodes. * Triggers a change event. @@ -184,11 +201,7 @@ // When saving document contents, save all document details, so that we capture all // changes in a single revision on the server. // We do this by delegating to the document object. - let content = this.get('content'); - if (Indigo.Preloads.provisionEid) { - content = `${content}`; - } - this.document.attributes.content = content; + this.document.attributes.content = this.wrapInAkn(this.get('content')); this.document.attributes.provision_eid = Indigo.Preloads.provisionEid; var result = this.document.save(); // XXX works around https://github.com/Code4SA/indigo/issues/20 by not parsing diff --git a/indigo_app/static/javascript/indigo/views/document_italics_terms.js b/indigo_app/static/javascript/indigo/views/document_italics_terms.js index a1b2a2b27..b78bc87d9 100644 --- a/indigo_app/static/javascript/indigo/views/document_italics_terms.js +++ b/indigo_app/static/javascript/indigo/views/document_italics_terms.js @@ -36,16 +36,9 @@ }, markUpItalics: function(e) { - var self = this, + let self = this, $btn = this.$el.find('.mark-up-italics'), - data = {'document': this.model.document.toJSON()}; - - let content = this.model.toXml(); - if (Indigo.Preloads.provisionEid) { - content = `${content}`; - data.document.provision_eid = Indigo.Preloads.provisionEid; - } - data.document.content = content; + data = this.model.toSimplifiedJSON(); this.$('a[href="#this-document-italics-terms"]').click(); @@ -60,7 +53,7 @@ contentType: "application/json; charset=utf-8", dataType: "json"}) .then(function(response) { - self.model.set('content', response.document.content); + self.model.set('content', response.xml); }) .always(function() { $btn From b3009f45abcce1993edbf0f8e25b673388528a6c Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:10:31 +0200 Subject: [PATCH 07/28] new ManipulateXmlView superclass for all four views --- indigo_api/serializers.py | 1 - indigo_api/views/documents.py | 75 ++++++++++++----------------------- 2 files changed, 26 insertions(+), 50 deletions(-) diff --git a/indigo_api/serializers.py b/indigo_api/serializers.py index b6593e07c..e08a2ab07 100644 --- a/indigo_api/serializers.py +++ b/indigo_api/serializers.py @@ -463,7 +463,6 @@ def update_document(self): if self.validated_data.get('is_portion'): document.work.work_uri.doctype = 'portion' document.content = self.validated_data.get('xml') - return document def updated_xml(self): # in provision mode, unwrap the akn tag as we don't want the 'Entire document' option for editing diff --git a/indigo_api/views/documents.py b/indigo_api/views/documents.py index fad4aa930..7e428d5f9 100644 --- a/indigo_api/views/documents.py +++ b/indigo_api/views/documents.py @@ -364,76 +364,53 @@ def post(self, request, document_id): return Response({'output': document.to_html()}) -class LinkTermsView(DocumentResourceView, APIView): - """ Support for running term discovery and linking on a document. - """ +class ManipulateXmlView(DocumentResourceView, APIView): def post(self, request, document_id): serializer = DocumentAPISerializer(instance=self.document, data=self.request.data) - serializer.fields['document'].fields['content'].required = True serializer.is_valid(raise_exception=True) - document = serializer.fields['document'].update_document(self.document, serializer.validated_data['document']) + serializer.update_document() + self.manipulate_xml() + return Response({'xml': serializer.updated_xml()}) - self.link_terms(document) + def manipulate_xml(self): + raise NotImplementedError() - return Response({'document': {'content': document.document_xml}}) - def link_terms(self, doc): - finder = plugins.for_document('terms', doc) +class LinkTermsView(ManipulateXmlView): + """ Support for running term discovery and linking on a document. + """ + def manipulate_xml(self): + # TODO: do the two different steps separately and a bit differently in provision mode + finder = plugins.for_document('terms', self.document) if finder: - finder.find_terms_in_document(doc) + finder.find_terms_in_document(self.document) -class LinkReferencesView(DocumentResourceView, APIView): +class LinkReferencesView(ManipulateXmlView): """ Find and link internal references and references to other works. """ - def post(self, request, document_id): - serializer = DocumentAPISerializer(instance=self.document, data=self.request.data) - serializer.fields['document'].fields['content'].required = True - serializer.is_valid(raise_exception=True) - document = serializer.fields['document'].update_document(self.document, serializer.validated_data['document']) - - self.find_references(document) - - return Response({'document': {'content': document.document_xml}}) - - def find_references(self, document): - markup_document_refs(document) + def manipulate_xml(self): + # TODO: markup all references and only return the relevant portion in provision mode? + markup_document_refs(self.document) -class MarkUpItalicsTermsView(DocumentResourceView, APIView): +class MarkUpItalicsTermsView(ManipulateXmlView): """ Find and mark up italics terms. """ - def post(self, request, document_id): - serializer = DocumentAPISerializer(instance=self.document, data=self.request.data) - serializer.is_valid(raise_exception=True) - document = serializer.update_document() - self.mark_up_italics(document) - return Response({'xml': serializer.updated_xml()}) - - def mark_up_italics(self, document): - italics_terms_finder = plugins.for_document('italics-terms', document) - italics_terms = document.work.country.italics_terms + def manipulate_xml(self): + italics_terms_finder = plugins.for_document('italics-terms', self.document) + italics_terms = self.document.work.country.italics_terms if italics_terms_finder and italics_terms: - italics_terms_finder.mark_up_italics_in_document(document, italics_terms) + italics_terms_finder.mark_up_italics_in_document(self.document, italics_terms) -class SentenceCaseHeadingsView(DocumentResourceView, APIView): +class SentenceCaseHeadingsView(ManipulateXmlView): """ Sentence case headings. Also apply accents as needed / relevant. """ - def post(self, request, document_id): - serializer = DocumentAPISerializer(instance=self.document, data=self.request.data) - serializer.fields['document'].fields['content'].required = True - serializer.is_valid(raise_exception=True) - document = serializer.fields['document'].update_document(self.document, serializer.validated_data['document']) - - self.sentence_case(document) - - return Response({'document': {'content': document.document_xml}}) - - def sentence_case(self, document): - sentence_caser = plugins.for_document('sentence-caser', document) + def manipulate_xml(self): + sentence_caser = plugins.for_document('sentence-caser', self.document) if sentence_caser: - sentence_caser.sentence_case_headings_in_document(document) + sentence_caser.sentence_case_headings_in_document(self.document) class DocumentDiffView(DocumentResourceView, APIView): From 645c0ba325467e2efb2cc13e1ed8512747763f03 Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Mon, 13 Jan 2025 09:14:54 +0200 Subject: [PATCH 08/28] other JS views use the new pattern too --- .../javascript/indigo/views/document_defined_terms.js | 7 ++----- .../static/javascript/indigo/views/document_references.js | 6 ++---- .../javascript/indigo/views/document_sentences_caser.js | 6 ++---- .../templates/indigo_api/document/_italics_terms.html | 2 +- indigo_app/templates/indigo_api/document/_toolbar.html | 6 +++--- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/indigo_app/static/javascript/indigo/views/document_defined_terms.js b/indigo_app/static/javascript/indigo/views/document_defined_terms.js index c679aeb9d..e54359aa0 100644 --- a/indigo_app/static/javascript/indigo/views/document_defined_terms.js +++ b/indigo_app/static/javascript/indigo/views/document_defined_terms.js @@ -38,10 +38,7 @@ linkTerms: function(e) { var self = this, $btn = this.$el.find('.link-terms'), - data = {}; - - data.document = this.model.document.toJSON(); - data.document.content = this.model.toXml(); + data = this.model.toSimplifiedJSON(); $btn .prop('disabled', true) @@ -54,7 +51,7 @@ contentType: "application/json; charset=utf-8", dataType: "json"}) .then(function(response) { - self.model.set('content', response.document.content); + self.model.set('content', response.xml); }) .always(function() { $btn diff --git a/indigo_app/static/javascript/indigo/views/document_references.js b/indigo_app/static/javascript/indigo/views/document_references.js index 665e3c4cc..5584d1dad 100644 --- a/indigo_app/static/javascript/indigo/views/document_references.js +++ b/indigo_app/static/javascript/indigo/views/document_references.js @@ -53,9 +53,7 @@ findReferences: function(e) { var self = this, $btn = this.$el.find('.find-references'), - data = {'document': this.model.document.toJSON()}; - - data.document.content = this.model.toXml(); + data = this.model.toSimplifiedJSON(); $btn .prop('disabled', true) @@ -68,7 +66,7 @@ contentType: "application/json; charset=utf-8", dataType: "json"}) .then(function(response) { - self.model.set('content', response.document.content); + self.model.set('content', response.xml); }) .always(function() { $btn diff --git a/indigo_app/static/javascript/indigo/views/document_sentences_caser.js b/indigo_app/static/javascript/indigo/views/document_sentences_caser.js index 18f8db75a..54c4adef9 100644 --- a/indigo_app/static/javascript/indigo/views/document_sentences_caser.js +++ b/indigo_app/static/javascript/indigo/views/document_sentences_caser.js @@ -15,9 +15,7 @@ sentenceCaseHeadings: function(e) { let self = this, - data = {'document': this.model.document.toJSON()}; - - data.document.content = this.model.toXml(); + data = this.model.toSimplifiedJSON(); $.ajax({ url: this.model.document.url() + '/analysis/sentence-case-headings', @@ -26,7 +24,7 @@ contentType: "application/json; charset=utf-8", dataType: "json"}) .then(function(response) { - self.model.set('content', response.document.content); + self.model.set('content', response.xml); }); }, }); diff --git a/indigo_app/templates/indigo_api/document/_italics_terms.html b/indigo_app/templates/indigo_api/document/_italics_terms.html index 06db13d44..93a9d3373 100644 --- a/indigo_app/templates/indigo_api/document/_italics_terms.html +++ b/indigo_app/templates/indigo_api/document/_italics_terms.html @@ -70,7 +70,7 @@ {{else}} - {% endverbatim %}{% trans 'No italicised terms.' %}{% verbatim %}. + {% endverbatim %}{% trans 'No italicised terms.' %}{% verbatim %} {{/if}} {% endverbatim %} diff --git a/indigo_app/templates/indigo_api/document/_toolbar.html b/indigo_app/templates/indigo_api/document/_toolbar.html index f943d1cbd..8f8df5f17 100644 --- a/indigo_app/templates/indigo_api/document/_toolbar.html +++ b/indigo_app/templates/indigo_api/document/_toolbar.html @@ -29,17 +29,17 @@ diff --git a/indigo_app/templates/indigo_api/document/show.html b/indigo_app/templates/indigo_api/document/show.html index 7c0ede85a..2df3f6080 100644 --- a/indigo_app/templates/indigo_api/document/show.html +++ b/indigo_app/templates/indigo_api/document/show.html @@ -109,7 +109,7 @@
{% include "indigo_api/document/_revisions.html" %} - {% include "indigo_api/document/_defined_terms.html" %} + {% include "indigo_api/document/_defined_terms.html" with provision_eid=provision_eid %} {% include "indigo_api/document/_references.html" %} {% include "indigo_api/document/_annotations.html" %} {% include "indigo_api/document/_insert_image_modal.html" %} From ec891e0cdc1fcc9e49f873eb1a52ca78fc654f5f Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:15:00 +0200 Subject: [PATCH 24/28] rename method --- indigo/analysis/terms/base.py | 2 +- indigo_api/views/documents.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/indigo/analysis/terms/base.py b/indigo/analysis/terms/base.py index e93b8f020..d26b1a0a4 100644 --- a/indigo/analysis/terms/base.py +++ b/indigo/analysis/terms/base.py @@ -51,7 +51,7 @@ def find_terms(self, doc): self.find_term_references(doc, terms) self.renumber_terms(doc) - def link_terms_in_provision(self, document): + def link_terms_in_document(self, document): """ Passively link defined terms in a Document while editing in provision mode. """ root = etree.fromstring(document.doc.to_xml(encoding='unicode')) diff --git a/indigo_api/views/documents.py b/indigo_api/views/documents.py index 101249d09..294232800 100644 --- a/indigo_api/views/documents.py +++ b/indigo_api/views/documents.py @@ -389,7 +389,7 @@ def manipulate_xml(self): finder = plugins.for_document('terms', self.document) if finder: if self.serializer.validated_data.get('provision_eid'): - finder.link_terms_in_provision(self.document) + finder.link_terms_in_document(self.document) else: finder.find_terms_in_document(self.document) From ec209242f74a677244a8ca05c21c3721356dcb6d Mon Sep 17 00:00:00 2001 From: edith <32566441+goose-life@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:17:54 +0200 Subject: [PATCH 25/28] Update indigo_app/templates/indigo_api/document/_defined_terms.html Co-authored-by: Greg Kempe --- indigo_app/templates/indigo_api/document/_defined_terms.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indigo_app/templates/indigo_api/document/_defined_terms.html b/indigo_app/templates/indigo_api/document/_defined_terms.html index 502521c9e..d8bee4faa 100644 --- a/indigo_app/templates/indigo_api/document/_defined_terms.html +++ b/indigo_app/templates/indigo_api/document/_defined_terms.html @@ -18,7 +18,7 @@ {% else %}

- {% trans 'In provision mode, only passive references that have already been marked up can be linked.' %} + {% trans 'Only uses of defined terms can be linked while editing a provision.' %} {% trans 'To mark up definitions, even in this provision, you need to edit the full document.' %}

{% endif %} From 5ed13de0183ca8633521b3af49701fa316f56773 Mon Sep 17 00:00:00 2001 From: edith <32566441+goose-life@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:18:11 +0200 Subject: [PATCH 26/28] Update indigo_app/templates/indigo_api/document/_defined_terms.html Co-authored-by: Greg Kempe --- indigo_app/templates/indigo_api/document/_defined_terms.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indigo_app/templates/indigo_api/document/_defined_terms.html b/indigo_app/templates/indigo_api/document/_defined_terms.html index d8bee4faa..bf902a728 100644 --- a/indigo_app/templates/indigo_api/document/_defined_terms.html +++ b/indigo_app/templates/indigo_api/document/_defined_terms.html @@ -19,7 +19,7 @@

{% trans 'Only uses of defined terms can be linked while editing a provision.' %} - {% trans 'To mark up definitions, even in this provision, you need to edit the full document.' %} + {% trans 'To mark up definitions, edit the full document.' %}

{% endif %} From 5f8ba8d135b3b3a8ec76804620f087ed5df8ca91 Mon Sep 17 00:00:00 2001 From: goose-life <32566441+goose-life@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:31:04 +0200 Subject: [PATCH 27/28] fix test --- indigo_api/tests/test_analysis_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indigo_api/tests/test_analysis_api.py b/indigo_api/tests/test_analysis_api.py index 069eb62dd..a49bd5bcb 100644 --- a/indigo_api/tests/test_analysis_api.py +++ b/indigo_api/tests/test_analysis_api.py @@ -115,8 +115,7 @@ def test_link_terms_portion(self): content = response.data['xml'] assert_true(content.startswith(' Date: Fri, 17 Jan 2025 09:38:08 +0200 Subject: [PATCH 28/28] deal with missing provision_eid differently --- indigo_app/templates/indigo_api/document/_defined_terms.html | 4 ++-- indigo_app/templates/indigo_api/document/show.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/indigo_app/templates/indigo_api/document/_defined_terms.html b/indigo_app/templates/indigo_api/document/_defined_terms.html index bf902a728..c7ca4b170 100644 --- a/indigo_app/templates/indigo_api/document/_defined_terms.html +++ b/indigo_app/templates/indigo_api/document/_defined_terms.html @@ -8,7 +8,7 @@