@hmcts/ccd-case-ui-toolkit 7.4.2-broken-access → 7.4.2-exui-5220-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14787,7 +14787,7 @@ class CaseFileViewFieldComponent {
14787
14787
  }
14788
14788
  setMediaViewerFile(document) {
14789
14789
  const documentDetails = {
14790
- document_binary_url: this.withLegacyDocumentAccessContext(this.documentManagementService.getDocumentBinaryUrl(document)),
14790
+ document_binary_url: document.document_binary_url,
14791
14791
  document_filename: document.document_filename,
14792
14792
  content_type: document.content_type
14793
14793
  };
@@ -14802,19 +14802,6 @@ class CaseFileViewFieldComponent {
14802
14802
  const mediaViewerInfo = this.documentManagementService.getMediaViewerInfo(documentDetails);
14803
14803
  this.currentDocument = JSON.parse(mediaViewerInfo);
14804
14804
  }
14805
- withLegacyDocumentAccessContext(documentBinaryUrl) {
14806
- if (!documentBinaryUrl || !this.caseId) {
14807
- return documentBinaryUrl;
14808
- }
14809
- const [path, query = ''] = documentBinaryUrl.split('?');
14810
- if (!/^\/documents\/[^/]+\/binary\/?$/.test(path)) {
14811
- return documentBinaryUrl;
14812
- }
14813
- // XUI validates legacy document access against the case before proxying the binary request.
14814
- const searchParams = new URLSearchParams(query);
14815
- searchParams.set('caseId', this.caseId);
14816
- return `${path}?${searchParams.toString()}`;
14817
- }
14818
14805
  moveDocument(data) {
14819
14806
  const cid = this.route.snapshot.paramMap.get(CaseFileViewFieldComponent.PARAM_CASE_ID);
14820
14807
  const loadingToken = this.loadingService.register();
@@ -27417,8 +27404,12 @@ class WriteRichTextAreaFieldComponent extends AbstractFieldWriteComponent {
27417
27404
  this.removeUnsupportedMarkup(documentElement);
27418
27405
  this.normaliseDateRangeSpacing(documentElement);
27419
27406
  this.removeUnsupportedAttributes(documentElement);
27407
+ const hasMeaningfulContent = this.hasMeaningfulRichTextContent(documentElement);
27408
+ if (hasMeaningfulContent) {
27409
+ this.preserveDocmosisBlankParagraphs(documentElement);
27410
+ }
27420
27411
  const sanitisedValue = sanitiseRichTextDocument(documentElement);
27421
- return this.hasMeaningfulRichTextContent(documentElement)
27412
+ return hasMeaningfulContent
27422
27413
  ? this.normalisePlainTextValue(sanitisedValue)
27423
27414
  : '';
27424
27415
  }
@@ -27438,11 +27429,22 @@ class WriteRichTextAreaFieldComponent extends AbstractFieldWriteComponent {
27438
27429
  this.removeUnsupportedMarkup(documentElement);
27439
27430
  this.normaliseDateRangeSpacing(documentElement);
27440
27431
  this.removeUnsupportedAttributes(documentElement);
27432
+ const hasMeaningfulContent = this.hasMeaningfulRichTextContent(documentElement);
27433
+ if (hasMeaningfulContent) {
27434
+ this.preserveDocmosisBlankParagraphs(documentElement);
27435
+ }
27441
27436
  const sanitisedValue = sanitiseRichTextDocument(documentElement);
27442
- return this.hasMeaningfulRichTextContent(documentElement)
27437
+ return hasMeaningfulContent
27443
27438
  ? this.normalisePlainTextValue(sanitisedValue)
27444
27439
  : '';
27445
27440
  }
27441
+ /**
27442
+ * Gives intentionally blank paragraphs content so Docmosis preserves them as blank lines.
27443
+ * This runs only when the document has meaningful content, so a completely empty field remains empty.
27444
+ */
27445
+ preserveDocmosisBlankParagraphs(documentElement) {
27446
+ this.replaceBlankParagraphContent(documentElement, '\u00a0');
27447
+ }
27446
27448
  hasMeaningfulRichTextContent(documentElement) {
27447
27449
  const visibleText = (documentElement.body.textContent || '')
27448
27450
  .replace(/[\s\u00a0\u200b-\u200d\ufeff]/g, '');
@@ -27563,7 +27565,8 @@ class WriteRichTextAreaFieldComponent extends AbstractFieldWriteComponent {
27563
27565
  emitEvent: false,
27564
27566
  emitModelToViewChange: false
27565
27567
  });
27566
- if (normalisedValue || this.editorHasMeaningfulRichTextContent()) {
27568
+ if ((normalisedValue || this.editorHasMeaningfulRichTextContent())
27569
+ && !this.differsOnlyByDocmosisBlankParagraphs(value, normalisedValue)) {
27567
27570
  this.editor.setContent(normalisedValue || '');
27568
27571
  }
27569
27572
  }
@@ -27571,6 +27574,34 @@ class WriteRichTextAreaFieldComponent extends AbstractFieldWriteComponent {
27571
27574
  this.isNormalisingValue = false;
27572
27575
  }
27573
27576
  }
27577
+ differsOnlyByDocmosisBlankParagraphs(value, normalisedValue) {
27578
+ if (!value || !normalisedValue) {
27579
+ return false;
27580
+ }
27581
+ const originalDocument = new DOMParser().parseFromString(value, 'text/html');
27582
+ const normalisedDocument = new DOMParser().parseFromString(normalisedValue, 'text/html');
27583
+ this.clearBlankParagraphs(originalDocument);
27584
+ this.clearBlankParagraphs(normalisedDocument);
27585
+ return originalDocument.body.innerHTML === normalisedDocument.body.innerHTML;
27586
+ }
27587
+ /**
27588
+ * Canonicalises visually blank paragraphs to <p></p> before comparing two HTML values.
27589
+ * This lets the editor avoid reloading when only the Docmosis blank-line representation changed.
27590
+ */
27591
+ clearBlankParagraphs(documentElement) {
27592
+ this.replaceBlankParagraphContent(documentElement, '');
27593
+ }
27594
+ replaceBlankParagraphContent(documentElement, replacement) {
27595
+ const paragraphs = Array.prototype.slice.call(documentElement.body.querySelectorAll('p'));
27596
+ paragraphs.forEach((paragraph) => {
27597
+ // Ignore standard whitespace (\s), non-breaking spaces (U+00A0), zero-width characters
27598
+ // (U+200B–U+200D), and the byte-order mark (U+FEFF) when checking for visible text.
27599
+ const visibleText = (paragraph.textContent || '').replace(/[\s\u00a0\u200b-\u200d\ufeff]/g, '');
27600
+ if (!visibleText && !paragraph.querySelector('hr')) {
27601
+ paragraph.textContent = replacement;
27602
+ }
27603
+ });
27604
+ }
27574
27605
  editorHasMeaningfulRichTextContent() {
27575
27606
  const documentNode = this.editor.view.state.doc;
27576
27607
  const visibleText = documentNode.textContent.replace(/[\s\u00a0\u200b-\u200d\ufeff]/g, '');
@@ -35635,18 +35666,19 @@ class ReadFieldsFilterPipe {
35635
35666
  const collectionItemValue = ReadFieldsFilterPipe.getCollectionItemValue(complexField);
35636
35667
  if (Object.keys(collectionItemValue).length > 0) {
35637
35668
  return {
35638
- checkConditionalShowAgainst: Object.assign(collectionItemValue, currentValues),
35669
+ checkConditionalShowAgainst: { ...collectionItemValue, ...currentValues },
35639
35670
  formGroupAvailable: false
35640
35671
  };
35641
35672
  }
35642
35673
  return {
35643
- checkConditionalShowAgainst: Object.assign(checkConditionalShowAgainst, currentValues),
35674
+ checkConditionalShowAgainst: { ...checkConditionalShowAgainst, ...currentValues },
35644
35675
  formGroupAvailable: false
35645
35676
  };
35646
35677
  }
35647
35678
  static resolveFallbackConditionalShowContext(checkConditionalShowAgainst, currentValues) {
35648
35679
  return {
35649
- checkConditionalShowAgainst: Object.assign(checkConditionalShowAgainst, currentValues),
35680
+ // Contexts are local to this render; never copy sibling values into shared form data.
35681
+ checkConditionalShowAgainst: { ...checkConditionalShowAgainst, ...currentValues },
35650
35682
  formGroupAvailable: false
35651
35683
  };
35652
35684
  }
@@ -35659,6 +35691,11 @@ class ReadFieldsFilterPipe {
35659
35691
  return { checkConditionalShowAgainst, formGroupAvailable };
35660
35692
  }
35661
35693
  if (idPrefix !== '') {
35694
+ // A collection item already supplies its own condition values. Do not rely on
35695
+ // its collection's name having been flattened into the root by another render.
35696
+ if (complexField.parent?.field_type?.type === 'Collection') {
35697
+ return { checkConditionalShowAgainst: currentValues, formGroupAvailable: false };
35698
+ }
35662
35699
  return ReadFieldsFilterPipe.resolvePrefixedConditionalShowContext(checkConditionalShowAgainst, currentValues, idPrefix);
35663
35700
  }
35664
35701
  if (path === 'parent_value' && ReadFieldsFilterPipe.findAncestorOfType(complexField, 'Collection')) {