@hmcts/rpx-xui-common-lib 2.1.3-angular-upgrade-11 → 2.1.4-angular-upgrade-11

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.
Files changed (61) hide show
  1. package/bundles/hmcts-rpx-xui-common-lib.umd.js +2310 -2427
  2. package/bundles/hmcts-rpx-xui-common-lib.umd.js.map +1 -1
  3. package/bundles/hmcts-rpx-xui-common-lib.umd.min.js +1 -1
  4. package/bundles/hmcts-rpx-xui-common-lib.umd.min.js.map +1 -1
  5. package/esm2015/hmcts-rpx-xui-common-lib.js +3 -65
  6. package/esm2015/lib/components/accessibility/accessibility.component.js +2 -2
  7. package/esm2015/lib/components/find-location/find-location.component.js +6 -2
  8. package/esm2015/lib/components/generic-filter/generic-filter.component.js +15 -9
  9. package/esm2015/lib/components/search-location/search-location.component.js +22 -3
  10. package/esm2015/lib/exui-common-lib.module.js +21 -6
  11. package/esm2015/lib/models/filter.model.js +1 -1
  12. package/esm2015/lib/models/index.js +2 -1
  13. package/esm2015/lib/models/location.model.js +7 -2
  14. package/esm2015/lib/services/find-person/find-person.service.js +3 -3
  15. package/esm2015/lib/services/locations/location.service.js +3 -3
  16. package/esm2015/public-api.js +76 -8
  17. package/fesm2015/hmcts-rpx-xui-common-lib.js +1952 -1987
  18. package/fesm2015/hmcts-rpx-xui-common-lib.js.map +1 -1
  19. package/hmcts-rpx-xui-common-lib.d.ts +2 -64
  20. package/hmcts-rpx-xui-common-lib.metadata.json +1 -1
  21. package/lib/components/find-location/find-location.component.d.ts +3 -2
  22. package/lib/components/search-location/search-location.component.d.ts +5 -2
  23. package/lib/exui-common-lib.module.d.ts +0 -33
  24. package/lib/models/filter.model.d.ts +2 -0
  25. package/lib/models/index.d.ts +1 -0
  26. package/lib/models/location.model.d.ts +11 -0
  27. package/lib/services/locations/location.service.d.ts +2 -2
  28. package/package.json +1 -1
  29. package/public-api.d.ts +78 -7
  30. package/esm2015/lib/components/index.js +0 -2
  31. package/esm2015/lib/components/public_api.js +0 -33
  32. package/esm2015/lib/directives/index.js +0 -2
  33. package/esm2015/lib/directives/public-api.js +0 -3
  34. package/esm2015/lib/gov-ui/components/index.js +0 -2
  35. package/esm2015/lib/gov-ui/components/public_api.js +0 -22
  36. package/esm2015/lib/gov-ui/gov-ui.service.js +0 -13
  37. package/esm2015/lib/gov-ui/index.js +0 -2
  38. package/esm2015/lib/gov-ui/public_api.js +0 -8
  39. package/esm2015/lib/gov-ui/validators/checkboxes-be-checked.validator.js +0 -18
  40. package/esm2015/lib/gov-ui/validators/date.validator.js +0 -15
  41. package/esm2015/lib/gov-ui/validators/index.js +0 -2
  42. package/esm2015/lib/gov-ui/validators/public_api.js +0 -7
  43. package/esm2015/lib/gov-ui/validators/radio-group.validator.js +0 -15
  44. package/esm2015/lib/services/index.js +0 -2
  45. package/esm2015/lib/services/public-api.js +0 -20
  46. package/lib/components/index.d.ts +0 -1
  47. package/lib/components/public_api.d.ts +0 -32
  48. package/lib/directives/index.d.ts +0 -1
  49. package/lib/directives/public-api.d.ts +0 -2
  50. package/lib/gov-ui/components/index.d.ts +0 -1
  51. package/lib/gov-ui/components/public_api.d.ts +0 -21
  52. package/lib/gov-ui/gov-ui.service.d.ts +0 -3
  53. package/lib/gov-ui/index.d.ts +0 -1
  54. package/lib/gov-ui/public_api.d.ts +0 -4
  55. package/lib/gov-ui/validators/checkboxes-be-checked.validator.d.ts +0 -2
  56. package/lib/gov-ui/validators/date.validator.d.ts +0 -2
  57. package/lib/gov-ui/validators/index.d.ts +0 -1
  58. package/lib/gov-ui/validators/public_api.d.ts +0 -3
  59. package/lib/gov-ui/validators/radio-group.validator.d.ts +0 -2
  60. package/lib/services/index.d.ts +0 -1
  61. package/lib/services/public-api.d.ts +0 -16
@@ -1,18 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, EventEmitter, ViewEncapsulation, Input, Output, Injectable, ChangeDetectionStrategy, ViewChild, Inject, InjectionToken, ChangeDetectorRef, ElementRef, Directive, ViewContainerRef, TemplateRef, NgModule } from '@angular/core';
2
+ import { Component, EventEmitter, ViewEncapsulation, Input, Output, Injectable, Inject, InjectionToken, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, ElementRef, Directive, ViewContainerRef, TemplateRef, NgModule } from '@angular/core';
3
3
  import * as i4 from '@angular/common';
4
- import { formatDate, DOCUMENT, CommonModule } from '@angular/common';
5
- import { Validators, FormArray, FormGroup, FormControl, FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
6
- import { BehaviorSubject, Subject, of, zip, combineLatest } from 'rxjs';
7
- import { distinctUntilChanged, map, tap, filter, debounceTime, mergeMap, switchMap, catchError, delay } from 'rxjs/operators';
4
+ import { DOCUMENT, formatDate, CommonModule } from '@angular/common';
5
+ import { FormBuilder, FormControl, FormGroup, Validators, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
6
+ import { map, tap, filter, debounceTime, mergeMap, switchMap, catchError, distinctUntilChanged, delay } from 'rxjs/operators';
8
7
  import * as i1 from '@angular/common/http';
9
8
  import { HttpClient } from '@angular/common/http';
10
- import { MatAutocompleteModule } from '@angular/material/autocomplete';
11
- import { MatInputModule } from '@angular/material/input';
12
- import { MatTabsModule } from '@angular/material/tabs';
9
+ import { of, zip, BehaviorSubject, Subject, combineLatest } from 'rxjs';
13
10
  import * as i1$1 from '@angular/router';
14
11
  import { Router, NavigationEnd, RouterModule } from '@angular/router';
15
- import { NgxPaginationModule, PaginatePipe } from 'ngx-pagination';
16
12
  import * as LDClient from 'launchdarkly-js-client-sdk';
17
13
  import * as i2 from '@angular/platform-browser';
18
14
  import { Title } from '@angular/platform-browser';
@@ -20,6 +16,10 @@ import * as i1$2 from '@ng-idle/core';
20
16
  import { DocumentInterruptSource, Idle } from '@ng-idle/core';
21
17
  import * as i2$1 from '@ng-idle/keepalive';
22
18
  import { Keepalive } from '@ng-idle/keepalive';
19
+ import { MatAutocompleteModule } from '@angular/material/autocomplete';
20
+ import { MatInputModule } from '@angular/material/input';
21
+ import { MatTabsModule } from '@angular/material/tabs';
22
+ import { NgxPaginationModule, PaginatePipe } from 'ngx-pagination';
23
23
 
24
24
  class AccessibilityComponent {
25
25
  constructor() {
@@ -28,7 +28,7 @@ class AccessibilityComponent {
28
28
  AccessibilityComponent.decorators = [
29
29
  { type: Component, args: [{
30
30
  selector: 'xuilib-accessibility',
31
- template: "<h1 class=\"govuk-heading-xl\" id=\"Accessibility-statement-for-Expert-UI\">Accessibility statement for Expert UI</h1>\n\n<ul class=\"govuk-list\">\n <li><a href=\"accessibility#immigration\">Immigration and Asylum</a></li>\n <li><a href=\"accessibility#family\">Family Public Law </a></li>\n</ul>\n\n<p class=\"govuk-body\">This website is run by HM Courts & Tribunals Service. We want as many people as possible to be\n able to use this website. For example, you should be able to:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>change colours, contrast levels and fonts</li>\n <li>zoom in up to 300% without the text spilling off the screen</li>\n <li>navigate most of the website using just a keyboard</li>\n <li>navigate most of the website using speech recognition software</li>\n <li>listen to most of the website using a screen reader (including the most recent versions of JAWS, NVDA and\n VoiceOver)\n </li>\n</ul>\n\n<p class=\"govuk-body\">We\u2019ve also made the website text as simple as possible to understand.</p>\n\n<p class=\"govuk-body\"><a rel=\"noopener noreferrer\" target=\"_blank\" href=\"https://mcmw.abilitynet.org.uk/\">AbilityNet</a>\n has advice on making your device easier to use if you have a disability.</p>\n\n<h2 class=\"govuk-heading-l\" id=\"How-accessible-this-website-is\">How accessible this website is</h2>\n\n<p class=\"govuk-body\">We know some parts of the website are not fully accessible:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>some pages are difficult to navigate using just a keyboard</li>\n <li>some pages can\u2019t be listened to in full using a screen reader</li>\n <li>some pages have problems with colour contrasts between text and background</li>\n <li>some PDFs may not be fully accessible to a screen reader</li>\n</ul>\n\n<h2 class=\"govuk-heading-l\" id=\"What-to-do-if-you-cannot-access-parts-of-this-website\">Feedback and contact\n information</h2>\n\n<p class=\"govuk-body\">If you need information on this website in a different format like accessible PDF, large print,\n easy read, audio recording or braille, you can:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>email: <a href=\"mailto:HMCTSforms@justice.gov.uk\"> HMCTSforms@justice.gov.uk</a></li>\n <li>call: +44 (0) 300 123 1711</li>\n <li>contact your service representative</li>\n</ul>\n\n<p class=\"govuk-body\">We\u2019ll consider your request and get back to you in 10 working days.</p>\n\n<h2 class=\"govuk-heading-l\" id=\"Reporting-accessibility-problems-with-this-website\">Reporting accessibility problems\n with this website</h2>\n\n<p class=\"govuk-body\">We\u2019re always looking to improve the accessibility of this website. If you find any problems not\n listed on this page or think we\u2019re not meeting accessibility requirements, contact:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>email: <a href=\"mailto:customer.service@justice.gov.uk\"> customer.service@justice.gov.uk</a></li>\n <li>telephone: +44 (0) 300 123 1711</li>\n</ul>\n\n<h2 class=\"govuk-heading-l\" id=\"Enforcement-procedure \">Enforcement procedure</h2>\n\n<p class=\"govuk-body\">The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector\n Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the \u2018accessibility\n regulations\u2019). </p>\n\n<p class=\"govuk-body\">If you\u2019re not happy with how we respond to your complaint, <a rel=\"noopener noreferrer\"\n target=\"_blank\"\n href=\"https://www.equalityadvisoryservice.com/\">contact\n the Equality Advisory and Support Service (EASS).</a></p>\n\n<h1 class=\"govuk-heading-l\" id=\"Contacting-us-by-phone-or-visiting-us-in-person\">Contacting us by phone or visiting us\n in person</h1>\n\n<p class=\"govuk-body\">We provide a text relay service for people who are D/deaf, hearing impaired or have a speech\n impediment.</p>\n\n<p class=\"govuk-body\">Our offices and tribunal venues have audio induction loops, or if you contact us before your visit\n we can arrange a British Sign Language (BSL) interpreter. You can also request step-free access or a foreign language\n interpreter.</p>\n\n<p class=\"govuk-body\">If you have a question about accessibility in our Tribunal venues, you can contact the First-tier\n Tribunal enquiry line: +44 (0) 300 123 1711. You can <a target=\"_blank\"\n href=\"https://courttribunalfinder.service.gov.uk/search/\">find\n the contact details for court and tribunal venues</a>. </p>\n\n<p class=\"govuk-body\">You can also contact your service representative for more information.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"Technical-information-about-this-website\u2019s-accessibility\">Technical information about\n this website\u2019s accessibility</h1>\n\n<p class=\"govuk-body\">HMCTS is committed to making its website accessible, in accordance with the Public Sector Bodies\n (Websites and Mobile Applications) (No.2) Accessibility Regulations 2018.</p>\n\n<p class=\"govuk-body\">This website is partially compliant with the <a rel=\"noopener noreferrer\" target=\"_blank\"\n href=\"https://www.w3.org/TR/WCAG21/\">Web Content\n Accessibility Guidelines version 2.1</a>, due to the non-compliances listed below.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"Non-accessible-content\">Non-accessible content </h1>\n\n<p class=\"govuk-body\">The content listed below is non-compliant for the following reasons.</p>\n\n<h2 class=\"govuk-heading-l\" id=\"Non-compliance-with-the-accessibility-regulations\">Non-compliance with the accessibility\n regulations</h2>\n\n<p class=\"govuk-body\">Some pages cannot be navigated completely using just a keyboard, so some people won\u2019t be able to\n tab through the pages. This fails WCAG 2.1 success criterion 2.1 (keyboard accessible).</p>\n\n<p class=\"govuk-body\">Some pages can\u2019t be listened to in full using a screen reader, so some people won\u2019t be able to\n access the information. This fails WCAG 2.1 success criterion 1.2.5 (audio description \u2013 prerecorded).</p>\n\n<p class=\"govuk-body\">Some of the contrast ratios don\u2019t meet the current accessibility requirements. This fails WCAG 2.1\n success criterion 1.4.3 (contrast \u2013 minimum).</p>\n\n<h3 class=\"govuk-heading-m\" id=\"immigration\">Immigration and Asylum</h3>\n\n<p class=\"govuk-body\">Some of the images on the service include text and are not accessible for some low vision users.\n We have identified a solution for this issue that we will implement as soon as possible.</p>\n\n<h3 class=\"govuk-heading-m\" id=\"family\">Family Public Law </h3>\n\n<ol class=\"govuk-list govuk-list--alpha\">\n <li>The navigation system used in family public law cannot be rendered well by screen readers, so features can\u2019t be\n listened to in full\n </li>\n <li>Some essential functions within the family public law digital service cannot be accessed properly using screen\n readers\n </li>\n <li>Some complex forms within the service will not be rendered correctly or cannot be listened to by screen readers\n </li>\n</ol>\n\n<h2 class=\"govuk-heading-m\" id=\"Disproportionate burden \">Disproportionate burden </h2>\n\n<p class=\"govuk-body\">For Manage organisation, Register organisation, Approve organisations and Manage cases, we found\n the following issues that are currently being triaged to find out if there is a disproportionate burden:</p>\n\n<ol class=\"govuk-list govuk-list--alpha\">\n <li>Screen readers can\u2019t switch between headers, read content in tabs and buttons</li>\n <li>Screen readers can\u2019t tab between radio buttons, read links or content</li>\n <li>Colour contrast ratios uneven between page background and content</li>\n <li>Some labels, fields, error messages and other content can\u2019t be clearly identified by screen readers and voice\n activation software\n </li>\n <li>Some page headings and titles don\u2019t follow a logical structure for screen readers</li>\n <li>The navigation of some pages isn\u2019t clear</li>\n <li>Some headings, links and button labels aren\u2019t clearly descriptive</li>\n</ol>\n\n<h2 class=\"govuk-heading-m\" id=\"Content-that\u2019s-not-within-the-scope-of-the-accessibility-regulations\">Content that\u2019s not\n within the scope of the accessibility regulations </h2>\n\n<p class=\"govuk-body\">PDFs, documents and attachments to email notifications published before 23 September 2018 may not\n meet accessibility standards. For example, they may not be structured so they\u2019re accessible to a screen reader.</p>\n\n<p class=\"govuk-body\">Any new PDFs or Word documents we publish will meet accessibility standards.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"what-to-improve-accessibility\">What we\u2019re doing to improve accessibility</h1>\n\n<p class=\"govuk-body\">We\u2019re committed to ensuring our services are accessible to all our users and that they comply with\n level AA of the Web Content Accessibility Guidelines \u2013 WCAG 2.1.</p>\n\n<p class=\"govuk-body\">We\u2019re actively working to improve the identified issues and make them AA-compliant by 23 September\n 2020. We\u2019re also continuing to improve all other AAA-level accessibility issues as we iterate the service.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"preparation-of-this-accessibility-statement\">Preparation of this accessibility\n statement</h1>\n\n<p class=\"govuk-body\">This statement was prepared on 16 September 2019. It was last reviewed on 16 September 2020.</p>\n\n<p class=\"govuk-body\">This website was last tested on 19 May 2020. The test was carried out by the <a target=\"_blank\"\n href=\"https://digitalaccessibilitycentre.org/\">Digital\n Accessibility Centre (DAC)</a>.</p>\n",
31
+ template: "<h1 class=\"govuk-heading-xl\" id=\"Accessibility-statement-for-Expert-UI\">Accessibility statement for Expert UI</h1>\n\n<ul class=\"govuk-list\">\n <li><a href=\"accessibility#immigration\">Immigration and Asylum</a></li>\n <li><a href=\"accessibility#family\">Family Public Law </a></li>\n</ul>\n\n<p class=\"govuk-body\">This website is run by HM Courts & Tribunals Service. We want as many people as possible to be\n able to use this website. For example, you should be able to:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>change colours, contrast levels and fonts</li>\n <li>zoom in up to 300% without the text spilling off the screen</li>\n <li>navigate most of the website using just a keyboard</li>\n <li>navigate most of the website using speech recognition software</li>\n <li>listen to most of the website using a screen reader (including the most recent versions of JAWS, NVDA and\n VoiceOver)\n </li>\n</ul>\n\n<p class=\"govuk-body\">We\u2019ve also made the website text as simple as possible to understand.</p>\n\n<p class=\"govuk-body\"><a rel=\"noopener noreferrer\" target=\"_blank\" href=\"https://mcmw.abilitynet.org.uk/\">AbilityNet</a>\n has advice on making your device easier to use if you have a disability.</p>\n\n<h2 class=\"govuk-heading-l\" id=\"How-accessible-this-website-is\">How accessible this website is</h2>\n\n<p class=\"govuk-body\">We know some parts of the website are not fully accessible:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>some pages are difficult to navigate using just a keyboard</li>\n <li>some pages can\u2019t be listened to in full using a screen reader</li>\n <li>some pages have problems with colour contrasts between text and background</li>\n <li>some PDFs may not be fully accessible to a screen reader</li>\n</ul>\n\n<h2 class=\"govuk-heading-l\" id=\"What-to-do-if-you-cannot-access-parts-of-this-website\">Feedback and contact\n information</h2>\n\n<p class=\"govuk-body\">If you need information on this website in a different format like accessible PDF, large print,\n easy read, audio recording or braille, you can:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>email: <a href=\"mailto:HMCTSforms@justice.gov.uk\"> HMCTSforms@justice.gov.uk</a></li>\n <li>call: +44 (0) 300 123 1711</li>\n <li>contact your service representative</li>\n</ul>\n\n<p class=\"govuk-body\">We\u2019ll consider your request and get back to you in 10 working days.</p>\n\n<h2 class=\"govuk-heading-l\" id=\"Reporting-accessibility-problems-with-this-website\">Reporting accessibility problems\n with this website</h2>\n\n<p class=\"govuk-body\">We\u2019re always looking to improve the accessibility of this website. If you find any problems not\n listed on this page or think we\u2019re not meeting accessibility requirements, contact:</p>\n\n<ul class=\"govuk-list govuk-list--bullet\">\n <li>email: <a href=\"mailto:customer.service@justice.gov.uk\"> customer.service@justice.gov.uk</a></li>\n <li>telephone: +44 (0) 300 123 1711</li>\n</ul>\n\n<h2 class=\"govuk-heading-l\" id=\"Enforcement-procedure \">Enforcement procedure</h2>\n\n<p class=\"govuk-body\">The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector\n Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the \u2018accessibility\n regulations\u2019). </p>\n\n<p class=\"govuk-body\">If you\u2019re not happy with how we respond to your complaint, <a rel=\"noopener noreferrer\"\n target=\"_blank\"\n href=\"https://www.equalityadvisoryservice.com/\">contact\n the Equality Advisory and Support Service (EASS).</a></p>\n\n<h1 class=\"govuk-heading-l\" id=\"Contacting-us-by-phone-or-visiting-us-in-person\">Contacting us by phone or visiting us\n in person</h1>\n\n<p class=\"govuk-body\">We provide a text relay service for people who are D/deaf, hearing impaired or have a speech\n impediment.</p>\n\n<p class=\"govuk-body\">Our offices and tribunal venues have audio induction loops, or if you contact us before your visit\n we can arrange a British Sign Language (BSL) interpreter. You can also request step-free access or a foreign language\n interpreter.</p>\n\n<p class=\"govuk-body\">If you have a question about accessibility in our Tribunal venues, you can contact the First-tier\n Tribunal enquiry line: +44 (0) 300 123 1711. You can <a target=\"_blank\"\n href=\"https://courttribunalfinder.service.gov.uk/search/\">find\n the contact details for court and tribunal venues</a>. </p>\n\n<p class=\"govuk-body\">You can also contact your service representative for more information.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"Technical-information-about-this-website\u2019s-accessibility\">Technical information about\n this website\u2019s accessibility</h1>\n\n<p class=\"govuk-body\">HMCTS is committed to making its website accessible, in accordance with the Public Sector Bodies\n (Websites and Mobile Applications) (No.2) Accessibility Regulations 2018.</p>\n\n<p class=\"govuk-body\">This website is partially compliant with the <a rel=\"noopener noreferrer\" target=\"_blank\"\n href=\"https://www.w3.org/TR/WCAG21/\">Web Content\n Accessibility Guidelines version 2.1</a>, due to the non-compliances listed below.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"Non-accessible-content\">Non-accessible content </h1>\n\n<p class=\"govuk-body\">The content listed below is non-compliant for the following reasons.</p>\n\n<h2 class=\"govuk-heading-l\" id=\"Non-compliance-with-the-accessibility-regulations\">Non-compliance with the accessibility\n regulations</h2>\n\n<p class=\"govuk-body\">Some pages cannot be navigated completely using just a keyboard, so some people won\u2019t be able to\n tab through the pages. This fails WCAG 2.1 success criterion 2.1 (keyboard accessible).</p>\n\n<p class=\"govuk-body\">Some pages can\u2019t be listened to in full using a screen reader, so some people won\u2019t be able to\n access the information. This fails WCAG 2.1 success criterion 1.2.5 (audio description \u2013 prerecorded).</p>\n\n<p class=\"govuk-body\">Some of the contrast ratios don\u2019t meet the current accessibility requirements. This fails WCAG 2.1\n success criterion 1.4.3 (contrast \u2013 minimum).</p>\n\n<h3 class=\"govuk-heading-m\" id=\"immigration\">Immigration and Asylum</h3>\n\n<p class=\"govuk-body\">Some of the images on the service include text and are not accessible for some low vision users.\n We have identified a solution for this issue that we will implement as soon as possible.</p>\n\n<h3 class=\"govuk-heading-m\" id=\"family\">Family Public Law </h3>\n\n<ol class=\"govuk-list govuk-list--alpha\">\n <li>The navigation system used in family public law cannot be rendered well by screen readers, so features can\u2019t be\n listened to in full\n </li>\n <li>Some essential functions within the family public law digital service cannot be accessed properly using screen\n readers\n </li>\n <li>Some complex forms within the service will not be rendered correctly or cannot be listened to by screen readers\n </li>\n</ol>\n\n<h2 class=\"govuk-heading-m\" id=\"Disproportionate burden \">Disproportionate burden </h2>\n\n<p class=\"govuk-body\">For Manage organisation, Register organisation, Approve organisations and Manage cases, we found\n the following issues that are currently being triaged to find out if there is a disproportionate burden:</p>\n\n<ol class=\"govuk-list govuk-list--alpha\">\n <li>Screen readers can\u2019t switch between headers, read content in tabs and buttons</li>\n <li>Screen readers can\u2019t tab between radio buttons, read links or content</li>\n <li>Colour contrast ratios uneven between page background and content</li>\n <li>Some labels, fields, error messages and other content can\u2019t be clearly identified by screen readers and voice\n activation software\n </li>\n <li>Some page headings and titles don\u2019t follow a logical structure for screen readers</li>\n <li>The navigation of some pages isn\u2019t clear</li>\n <li>Some headings, links and button labels aren\u2019t clearly descriptive</li>\n</ol>\n\n<h2 class=\"govuk-heading-m\" id=\"Content-that\u2019s-not-within-the-scope-of-the-accessibility-regulations\">Content that\u2019s not\n within the scope of the accessibility regulations </h2>\n\n<p class=\"govuk-body\">PDFs, documents and attachments to email notifications published before 23 September 2018 may not\n meet accessibility standards. For example, they may not be structured so they\u2019re accessible to a screen reader.</p>\n\n<p class=\"govuk-body\">Any new PDFs or Word documents we publish will meet accessibility standards.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"what-to-improve-accessibility\">What we\u2019re doing to improve accessibility</h1>\n\n<p class=\"govuk-body\">We\u2019re committed to ensuring our services are accessible to all our users and that they comply with\n level AA of the Web Content Accessibility Guidelines \u2013 WCAG 2.1.</p>\n\n<p class=\"govuk-body\">We\u2019re actively working to improve the identified issues and make them AA-compliant by 23 September\n 2020. We\u2019re also continuing to improve all other AAA-level accessibility issues as we iterate the service.</p>\n\n<h1 class=\"govuk-heading-l\" id=\"preparation-of-this-accessibility-statement\">Preparation of this accessibility\n statement</h1>\n\n<p class=\"govuk-body\">This statement was prepared on 16 September 2019. It was last reviewed on 16 September 2020.</p>\n\n<p class=\"govuk-body\">This website was last tested on 19 May 2020. The test was carried out by the <a target=\"_blank\"\n href=\"https://digitalaccessibilitycentre.org/\">Digital\n Accessibility Centre (DAC)</a>.</p>\n\n<h3 class=\"govuk-heading-m\">Family Private Law:</h3>\n\n<p class=\"govuk-body\">This service has not yet been tested for accessibility issues. In the future, we will conduct an\n accessibility audit in order to find out if there are any accessibility issues. The accessibility statement will be\n updated with any relevant changes that we find.</p>\n\n<p class=\"govuk-body\">If there are any issues with accessing information or using this website please contact:</p>\n\n<ol class=\"govuk-list govuk-list--bullet\">\n <li>Nicola Whitcher - 02380 384324</li>\n <li>Hannah Townley - 02380 384313</li>\n</ol>",
32
32
  styles: [".govuk-list--alpha{padding-left:20px;list-style-type:lower-alpha}"]
33
33
  },] }
34
34
  ];
@@ -226,6 +226,117 @@ ContactDetailsComponent.propDecorators = {
226
226
  data: [{ type: Input }]
227
227
  };
228
228
 
229
+ class CookieService {
230
+ constructor(doc) {
231
+ this.document = doc;
232
+ }
233
+ setCookie(key, value, expiryDate) {
234
+ const expiry = expiryDate ? ` expires=${expiryDate}` : '';
235
+ const cookie = `${key}=${value};${expiry}`;
236
+ this.document.cookie = cookie;
237
+ }
238
+ getCookie(key) {
239
+ const cookieValue = this.document.cookie
240
+ .split('; ')
241
+ .find(row => row.startsWith(`${key}=`))
242
+ .split('=')[1];
243
+ return cookieValue;
244
+ }
245
+ deleteCookie(key, path, domain) {
246
+ const pathValue = path ? `; path=${path}` : '';
247
+ const domainValue = domain ? `; domain=${domain}` : '';
248
+ this.document.cookie = `${key}=${pathValue}${domainValue}; expires=Thu, 01 Jan 1970 00:00:01 GMT; max-age=0`;
249
+ }
250
+ deleteCookieByPartialMatch(key, path, domain) {
251
+ this.document.cookie
252
+ .split('; ')
253
+ .filter(row => row.startsWith(`${key}`))
254
+ .forEach(element => {
255
+ this.deleteCookie(element.split('=')[0], path, domain);
256
+ });
257
+ }
258
+ checkCookie(key) {
259
+ return this.document.cookie.split('; ').some(item => item.trim().startsWith(`${key}=`));
260
+ }
261
+ }
262
+ CookieService.ɵprov = i0.ɵɵdefineInjectable({ factory: function CookieService_Factory() { return new CookieService(i0.ɵɵinject(i4.DOCUMENT)); }, token: CookieService, providedIn: "root" });
263
+ CookieService.decorators = [
264
+ { type: Injectable, args: [{
265
+ providedIn: 'root'
266
+ },] }
267
+ ];
268
+ CookieService.ctorParameters = () => [
269
+ { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
270
+ ];
271
+
272
+ const windowToken = new InjectionToken('Window');
273
+ function windowProvider() { return window; }
274
+
275
+ class CookieBannerComponent {
276
+ constructor(cookieService, window) {
277
+ this.cookieService = cookieService;
278
+ this.rejectionNotifier = new EventEmitter();
279
+ this.acceptanceNotifier = new EventEmitter();
280
+ this.isCookieBannerVisible = false;
281
+ this.window = window;
282
+ }
283
+ ngOnInit() {
284
+ this.setState();
285
+ }
286
+ acceptCookie() {
287
+ this.cookieService.setCookie(this.identifier, 'true', this.getExpiryDate());
288
+ this.setState(true);
289
+ }
290
+ rejectCookie() {
291
+ this.cookieService.setCookie(this.identifier, 'false', this.getExpiryDate());
292
+ this.setState(true);
293
+ }
294
+ setState(reload = false) {
295
+ this.isCookieBannerVisible = !this.cookieService.checkCookie(this.identifier);
296
+ if (this.areCookiesAccepted()) {
297
+ this.notifyAcceptance();
298
+ }
299
+ else {
300
+ this.notifyRejection();
301
+ }
302
+ if (reload) { // reload if any of the buttons are pressed
303
+ this.window.location.reload();
304
+ }
305
+ }
306
+ areCookiesAccepted() {
307
+ return this.cookieService.checkCookie(this.identifier) && this.cookieService.getCookie(this.identifier) === 'true';
308
+ }
309
+ notifyRejection() {
310
+ this.rejectionNotifier.emit();
311
+ }
312
+ notifyAcceptance() {
313
+ this.acceptanceNotifier.emit();
314
+ }
315
+ getExpiryDate() {
316
+ const now = new Date();
317
+ const time = now.getTime();
318
+ const expireTime = time + 31536000000; // in 365 days = 3600 * 1000 * 24 * 365
319
+ now.setTime(expireTime);
320
+ return now.toUTCString();
321
+ }
322
+ }
323
+ CookieBannerComponent.decorators = [
324
+ { type: Component, args: [{
325
+ selector: 'xuilib-cookie-banner',
326
+ template: "<div class=\"govuk-cookie-banner \" role=\"region\" attr.aria-label=\"'Cookies on {{appName}}'\" *ngIf=\"isCookieBannerVisible\">\n <div class=\"govuk-cookie-banner__message govuk-width-container\">\n\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-two-thirds\">\n <h2 class=\"govuk-cookie-banner__heading govuk-heading-m\">Cookies on {{appName}}</h2>\n\n <div class=\"govuk-cookie-banner__content\">\n <p>We use some essential cookies to make this service work.</p>\n <p>We\u2019d also like to use analytics cookies so we can understand how you use the service and make improvements.</p>\n </div>\n </div>\n </div>\n\n <div class=\"govuk-button-group\">\n <button value=\"accept\" type=\"button\" name=\"cookies\" class=\"govuk-button\" data-module=\"govuk-button\" (click)=\"acceptCookie()\">\n Accept analytics cookies\n </button>\n <button value=\"reject\" type=\"button\" name=\"cookies\" class=\"govuk-button\" data-module=\"govuk-button\" (click)=\"rejectCookie()\">\n Reject analytics cookies\n </button>\n <a class=\"govuk-link\" routerLink=\"/cookies\">View cookies</a>\n </div>\n </div>\n</div>"
327
+ },] }
328
+ ];
329
+ CookieBannerComponent.ctorParameters = () => [
330
+ { type: CookieService },
331
+ { type: undefined, decorators: [{ type: Inject, args: [windowToken,] }] }
332
+ ];
333
+ CookieBannerComponent.propDecorators = {
334
+ identifier: [{ type: Input }],
335
+ appName: [{ type: Input }],
336
+ rejectionNotifier: [{ type: Output }],
337
+ acceptanceNotifier: [{ type: Output }]
338
+ };
339
+
229
340
  var DateBadgeColour;
230
341
  (function (DateBadgeColour) {
231
342
  DateBadgeColour["RED"] = "hmcts-badge--red";
@@ -346,66 +457,32 @@ DueDateComponent.propDecorators = {
346
457
  mediumUrgencyCutoff: [{ type: Input }]
347
458
  };
348
459
 
349
- class FilterService {
350
- constructor() {
351
- this.givenErrors = new BehaviorSubject(null);
352
- this.isInitialSetting = false;
353
- this.filterSettings = {};
354
- this.streams = {};
355
- }
356
- persist(setting, persistence) {
357
- switch (persistence) {
358
- case 'local':
359
- this.persistLocal(setting);
360
- break;
361
- case 'session':
362
- this.persistSession(setting);
363
- break;
364
- default:
365
- break;
366
- }
367
- this.persistMemory(setting);
368
- this.updateStreams(setting);
369
- }
370
- get(id) {
371
- if (this.filterSettings[id]) {
372
- return this.filterSettings[id];
373
- }
374
- if (sessionStorage.getItem(id)) {
375
- return JSON.parse(window.sessionStorage.getItem(id));
376
- }
377
- if (localStorage.getItem(id)) {
378
- return JSON.parse(window.localStorage.getItem(id));
379
- }
380
- return null;
381
- }
382
- getStream(id) {
383
- if (!this.streams[id]) {
384
- this.streams[id] = new BehaviorSubject(this.get(id));
385
- }
386
- return this.streams[id].asObservable();
387
- }
388
- persistLocal(setting) {
389
- window.localStorage.setItem(setting.id, JSON.stringify(setting));
390
- }
391
- persistSession(setting) {
392
- window.sessionStorage.setItem(setting.id, JSON.stringify(setting));
393
- }
394
- persistMemory(setting) {
395
- this.filterSettings[setting.id] = setting;
396
- }
397
- updateStreams(setting) {
398
- if (this.streams[setting.id]) {
399
- this.streams[setting.id].next(setting);
400
- }
401
- }
460
+ /**
461
+ * Main Page Wrapper
462
+ * Responsible for:
463
+ * Wrapping content within the gov-uk html elements bellow
464
+ * @prop showBackLink - switch for back link
465
+ * @prop appHeaderTitle = appHeaderTitle
466
+ * @prop appFunctionalTitle = appFunctionalTitle
467
+ * @prop summaryErrors list of errors
468
+ * @prop back link, appHeaderTitle (appHeaderTitle), summaryErrors (array of errors)
469
+ */
470
+ class ExuiPageWrapperComponent {
471
+ constructor() { }
402
472
  }
403
- FilterService.ɵprov = i0.ɵɵdefineInjectable({ factory: function FilterService_Factory() { return new FilterService(); }, token: FilterService, providedIn: "root" });
404
- FilterService.decorators = [
405
- { type: Injectable, args: [{
406
- providedIn: 'root'
473
+ ExuiPageWrapperComponent.decorators = [
474
+ { type: Component, args: [{
475
+ selector: 'exui-page-wrapper',
476
+ template: "<div class=\"page\">\n <a *ngIf=\"backLink\" [routerLink]=\"backLink\" class=\"govuk-back-link\">Back</a>\n <div class=\"govuk-width-container\">\n <main id=\"content\" role=\"main\" class=\"govuk-main-wrapper\">\n <div class=\"govuk-grid-row\">\n <h1 *ngIf=\"title\" class=\"govuk-heading-xl\">\n <span *ngIf=\"fnTitle\" class=\"govuk-caption-xl\">{{fnTitle}}</span>\n {{title}}\n </h1>\n <ng-content>\n\n </ng-content>\n </div>\n </main>\n </div>\n</div>\n",
477
+ styles: [".page{width:100%}"]
407
478
  },] }
408
479
  ];
480
+ ExuiPageWrapperComponent.ctorParameters = () => [];
481
+ ExuiPageWrapperComponent.propDecorators = {
482
+ backLink: [{ type: Input }],
483
+ title: [{ type: Input }],
484
+ fnTitle: [{ type: Input }]
485
+ };
409
486
 
410
487
  function minSelectedValidator(min) {
411
488
  return (control) => {
@@ -428,2225 +505,2182 @@ function getValues(options, values) {
428
505
  }, []);
429
506
  }
430
507
 
431
- class GenericFilterComponent {
432
- constructor(filterService, fb) {
433
- this.filterService = filterService;
434
- this.fb = fb;
435
- this.submitted = false;
436
- }
437
- get config() {
438
- return this._config;
439
- }
440
- set config(value) {
441
- this._config = Object.assign(Object.assign({}, value), { fields: value.fields.map(field => (Object.assign(Object.assign({}, field), { displayMinSelectedError: false, displayMaxSelectedError: false }))) });
442
- this._config = value;
508
+ var BadgeColour;
509
+ (function (BadgeColour) {
510
+ BadgeColour["BADGE_RED"] = "hmcts-badge--red";
511
+ BadgeColour["BADGE_BLUE"] = "hmcts-badge--blue";
512
+ BadgeColour["BADGE_GREEN"] = "hmcts-badge--green";
513
+ })(BadgeColour || (BadgeColour = {}));
514
+
515
+ class AnonymousFeatureUser {
516
+ }
517
+ class LoggedInFeatureUser {
518
+ }
519
+
520
+ var BookingCheckType;
521
+ (function (BookingCheckType) {
522
+ BookingCheckType["NO_CHECK"] = "NO_CHECK";
523
+ BookingCheckType["BOOKINGS_AND_BASE"] = "BOOKINGS_AND_BASE";
524
+ BookingCheckType["POSSIBLE_BOOKINGS"] = "POSSIBLE_BOOKINGS";
525
+ })(BookingCheckType || (BookingCheckType = {}));
526
+
527
+ var PersonRole;
528
+ (function (PersonRole) {
529
+ PersonRole["JUDICIAL"] = "Judicial";
530
+ PersonRole["CASEWORKER"] = "Legal Ops";
531
+ PersonRole["ADMIN"] = "Admin";
532
+ PersonRole["ALL"] = "All";
533
+ })(PersonRole || (PersonRole = {}));
534
+ // Note: RoleCategory could replace PersonRole possibly
535
+ // However a lot of webapp logic is based on current PersonRole understanding
536
+ var RoleCategory;
537
+ (function (RoleCategory) {
538
+ RoleCategory["JUDICIAL"] = "JUDICIAL";
539
+ RoleCategory["CASEWORKER"] = "LEGAL_OPERATIONS";
540
+ RoleCategory["ADMIN"] = "ADMIN";
541
+ RoleCategory["ALL"] = "ALL";
542
+ })(RoleCategory || (RoleCategory = {}));
543
+
544
+ class RadioFilterFieldConfig {
545
+ }
546
+
547
+ class LocationService {
548
+ constructor(http) {
549
+ this.http = http;
443
550
  }
444
- get settings() {
445
- return this._settings;
551
+ /**
552
+ * @description getAllLocations from service Ids/location type/search term
553
+ * @param serviceIds: SSCS | SSCS,IA split with ','
554
+ * @param locationType: optional | hearing | case_management
555
+ * @param searchTerm: any search term for postcode | site name | venue name |court name | court address etc.
556
+ * @return Observable<LocationByEPIMMSModel[]>: Array of locationModel in Observable
557
+ */
558
+ getAllLocations(serviceIds, locationType, searchTerm, userLocations, bookingLocations) {
559
+ return this.http.post(`api/locations/getLocations`, { serviceIds, locationType, searchTerm, userLocations, bookingLocations });
446
560
  }
447
- set settings(value) {
448
- if (!value) {
449
- this.getSettings();
450
- }
451
- if (value && value.fields) {
452
- this.mergeDefaultFields(value);
453
- }
454
- this._settings = value;
561
+ /**
562
+ * @description searchLocations from service Ids/location type/search term
563
+ * @param serviceIds: BBA3 | BBA3,BFA1 split with ','
564
+ * @param locationType: optional | hearing | case_management
565
+ * @param searchTerm: any search term for postcode | site name | venue name |court name | court address etc.
566
+ * @return Observable<LocationByEPIMMSModel[]>: Array of locationModel in Observable
567
+ */
568
+ searchLocations(serviceIds, locationType, searchTerm) {
569
+ return this.http.get(`api/prd/location/getLocations?serviceIds=${serviceIds}&locationType=${locationType}&searchTerm=${searchTerm}`);
455
570
  }
456
- static addFormValidators(field) {
457
- const validators = [];
458
- if (field && field.minSelected) {
459
- validators.push(minSelectedValidator(field.minSelected));
460
- }
461
- if (field && field.maxSelected) {
462
- validators.push(maxSelectedValidator(field.maxSelected));
571
+ }
572
+ LocationService.ɵprov = i0.ɵɵdefineInjectable({ factory: function LocationService_Factory() { return new LocationService(i0.ɵɵinject(i1.HttpClient)); }, token: LocationService, providedIn: "root" });
573
+ LocationService.decorators = [
574
+ { type: Injectable, args: [{
575
+ providedIn: 'root'
576
+ },] }
577
+ ];
578
+ LocationService.ctorParameters = () => [
579
+ { type: HttpClient }
580
+ ];
581
+
582
+ class SessionStorageService {
583
+ /**
584
+ * Get an item from the session storage.
585
+ * If remove is true, the item will be removed once read
586
+ * @param removeAfterRead removed the key once it has been read
587
+ */
588
+ getItem(key, removeAfterRead = false) {
589
+ const item = sessionStorage.getItem(key);
590
+ if (removeAfterRead) {
591
+ this.removeItem(key);
463
592
  }
464
- return validators;
593
+ return item;
594
+ }
595
+ /**
596
+ * Set an item in the session storage.
597
+ */
598
+ setItem(key, value) {
599
+ sessionStorage.setItem(key, value);
600
+ }
601
+ /**
602
+ * Remove an item in the session storage.
603
+ */
604
+ removeItem(key) {
605
+ sessionStorage.removeItem(key);
606
+ }
607
+ /**
608
+ * Clear all the items held in session storage.
609
+ */
610
+ clear() {
611
+ sessionStorage.clear();
612
+ }
613
+ }
614
+ SessionStorageService.ɵprov = i0.ɵɵdefineInjectable({ factory: function SessionStorageService_Factory() { return new SessionStorageService(); }, token: SessionStorageService, providedIn: "root" });
615
+ SessionStorageService.decorators = [
616
+ { type: Injectable, args: [{
617
+ providedIn: 'root'
618
+ },] }
619
+ ];
620
+
621
+ class SearchLocationComponent {
622
+ constructor(locationService, sessionStorageService, fb, cd) {
623
+ this.locationService = locationService;
624
+ this.sessionStorageService = sessionStorageService;
625
+ this.fb = fb;
626
+ this.cd = cd;
627
+ this.disabled = null;
628
+ this.singleMode = false;
629
+ this.locationType = '';
630
+ this.serviceIds = '';
631
+ this.submitted = true;
632
+ this.delay = 500;
633
+ this.showAutocomplete = false;
634
+ this.locations = [];
635
+ this.locationSelected = new EventEmitter();
636
+ this.locationInputChanged = new EventEmitter();
637
+ this.searchLocationChanged = new EventEmitter();
638
+ this.minSearchCharacters = 3;
639
+ this.term = '';
640
+ this.pSelectedLocations = [];
641
+ this.pReset = true;
642
+ this.form = this.fb.group({
643
+ searchTerm: ['']
644
+ });
645
+ }
646
+ get reset() {
647
+ return this.pReset;
648
+ }
649
+ set reset(value) {
650
+ this.pReset = value;
651
+ this.resetSearchTerm();
652
+ }
653
+ get selectedLocations() {
654
+ return this.pSelectedLocations;
655
+ }
656
+ set selectedLocations(value) {
657
+ this.pSelectedLocations = value;
465
658
  }
466
659
  ngOnInit() {
467
- if (!this.settings) {
468
- this.getSettings();
660
+ if (this.singleMode && this.selectedLocations.length > 0) {
661
+ const location = this.selectedLocations[0];
662
+ this.form.controls.searchTerm.patchValue(location.site_name, { emitEvent: false, onlySelf: true });
469
663
  }
470
- this.mergeDefaultFields(this.settings);
471
- this.buildForm(this.config, this.settings);
472
- this.formSub = this.form.valueChanges.subscribe(() => this.submitted = false);
664
+ this.search();
473
665
  }
474
- ngOnDestroy() {
475
- if (this.formSub) {
476
- this.formSub.unsubscribe();
477
- }
666
+ filter(term) {
667
+ this.getLocations(term).pipe(map((locations) => this.removeSelectedLocations(locations)));
478
668
  }
479
- hidden(field, form) {
480
- if (!field.showCondition) {
481
- return false;
482
- }
483
- if (typeof field.showCondition === 'string') {
484
- const control = form.get(field.name);
485
- const [name, value] = field.showCondition.split('=');
486
- if (form.value && form.value[name] === value) {
487
- if (field.type === 'find-person') {
488
- control.get('email').setValidators(Validators.required);
489
- control.get('email').updateValueAndValidity();
490
- }
491
- else {
492
- control.setValidators(Validators.required);
493
- control.updateValueAndValidity();
494
- }
495
- return false;
496
- }
497
- else {
498
- if (field.type === 'find-person') {
499
- control.get('email').clearValidators();
500
- control.get('email').updateValueAndValidity();
501
- }
502
- else {
503
- control.clearValidators();
504
- control.updateValueAndValidity();
505
- }
506
- }
507
- }
508
- return true;
669
+ onSelectionChange(location) {
670
+ this.form.controls.searchTerm.patchValue(location.site_name, { emitEvent: false, onlySelf: true });
671
+ this.locationSelected.emit(location);
509
672
  }
510
- disabled(field, form) {
511
- if (!field.enableCondition) {
512
- return null;
513
- }
514
- if (typeof field.enableCondition === 'string') {
515
- const control = form.get(field.name);
516
- const [name, value] = field.enableCondition.split('=');
517
- if (form.value && form.value[name] === value) {
518
- if (field.type === 'find-person') {
519
- control.get('email').setValidators(Validators.required);
520
- control.get('email').updateValueAndValidity();
521
- }
522
- else {
523
- control.setValidators(Validators.required);
524
- control.updateValueAndValidity();
525
- }
526
- return null;
527
- }
528
- else {
529
- if (field.type === 'find-person') {
530
- control.get('email').clearValidators();
531
- control.get('email').updateValueAndValidity();
532
- }
533
- else {
534
- control.clearValidators();
535
- control.updateValueAndValidity();
536
- }
673
+ search() {
674
+ this.form.controls.searchTerm.valueChanges
675
+ .pipe(tap((term) => this.locationInputChanged.next(term)), tap(() => this.locations = []), tap((term) => this.term = term), filter(term => !!term && term.length >= this.minSearchCharacters), debounceTime(this.delay), mergeMap(value => this.getLocations(value)), map((locations) => this.removeSelectedLocations(locations))).subscribe(locations => {
676
+ this.locations = locations;
677
+ this.cd.markForCheck();
678
+ if (locations.length === 1 && this.term === locations[0].site_name && !this.singleMode) {
679
+ this.locationSelected.emit(locations[0]);
680
+ this.showAutocomplete = false;
681
+ return;
537
682
  }
538
- }
539
- // find-location is special case where need to reset textbox (by existing disabling functionality)
540
- // field.disable referred to component itself
541
- if (field.type === 'find-location') {
542
- return true;
543
- }
544
- // Note: field.disable decides whether to actually disable or not
545
- return field.disable ? field.disable : null;
683
+ this.showAutocomplete = true;
684
+ });
546
685
  }
547
- applyFilter(form) {
548
- this.submitted = true;
549
- form.markAsTouched();
550
- if (form.valid) {
551
- this._settings = {
552
- id: this.config.id,
553
- fields: this.getSelectedValues(form.value, this.config)
554
- };
555
- this.filterService.givenErrors.next(null);
556
- const settings = Object.assign(Object.assign({}, this.settings), { reset: false });
557
- this.filterService.persist(settings, this.config.persistence);
558
- }
559
- else {
560
- this.emitFormErrors(form);
561
- }
686
+ onInput() {
687
+ this.searchLocationChanged.emit();
562
688
  }
563
- // when domain changes ensure that person field is reset
564
- fieldChanged(field, form) {
565
- // TODO - Do similar with jurisdiction/service for caseworkers by services
566
- if (field.changeResetFields && field.changeResetFields.length) {
567
- for (const resetField of field.changeResetFields) {
568
- this.resetField(resetField, form);
569
- }
570
- }
689
+ getLocations(term) {
690
+ let userLocations;
691
+ let bookingLocations;
692
+ // Booking type info - can create more
693
+ // NO_CHECK - All work - Do not filter out locations - Default assumption
694
+ // ONLY_BOOKINGS - My work - Try to only show base locations/booking locations
695
+ // POSSIBLE_BOOKINGS - Create booking screen - Show only potential bookings
696
+ if (this.bookingCheck === BookingCheckType.BOOKINGS_AND_BASE) {
697
+ userLocations = JSON.parse(this.sessionStorageService.getItem('userLocations'));
698
+ bookingLocations = JSON.parse(this.sessionStorageService.getItem('bookingLocations'));
699
+ }
700
+ else if (this.bookingCheck === BookingCheckType.POSSIBLE_BOOKINGS) {
701
+ userLocations = JSON.parse(this.sessionStorageService.getItem('userLocations'));
702
+ this.serviceIds = JSON.parse(this.sessionStorageService.getItem('bookableServices'));
703
+ }
704
+ return this.locationService.getAllLocations(this.serviceIds, this.locationType, term, userLocations, bookingLocations);
571
705
  }
572
- // when user enters input change radio button
573
- inputChanged(field) {
574
- if (field.radioSelectionChange && typeof field.radioSelectionChange === 'string') {
575
- const [name, value] = field.enableCondition.split('=');
576
- this.form.get(name).patchValue(value);
577
- }
706
+ resetSearchTerm() {
707
+ this.form.controls.searchTerm.patchValue('', { emitEvent: false, onlySelf: true });
578
708
  }
579
- cancelFilter() {
580
- this.buildForm(this.config, this.settings, true);
581
- if (this.config && this.config.cancelSetting) {
582
- this._settings.fields = JSON.parse(JSON.stringify(this.config.cancelSetting.fields));
709
+ removeSelectedLocations(locations) {
710
+ if (this.singleMode) {
711
+ return locations;
583
712
  }
584
- const settings = Object.assign(Object.assign({}, this.settings), { reset: true });
585
- this.filterService.persist(settings, this.config.persistence);
586
- this.filterService.givenErrors.next(null);
587
- this.submitted = false;
713
+ return locations.filter(location => !this.selectedLocations.map(selectedLocation => selectedLocation.epimms_id).includes(location.epimms_id) && location.site_name);
588
714
  }
589
- updatePersonControls(values, field) {
590
- let keys;
591
- if (!values) {
592
- keys = Object.keys(this.form.get(field.name).value);
593
- }
594
- else {
595
- keys = Object.keys(values);
596
- }
597
- for (const key of keys) {
598
- if (this.form.get(field.name) && this.form.get(field.name).get(key)) {
599
- const value = values && values[key] ? values[key] : null;
600
- this.form.get(field.name).get(key).patchValue(value);
601
- }
602
- }
715
+ }
716
+ SearchLocationComponent.decorators = [
717
+ { type: Component, args: [{
718
+ selector: 'exui-search-location',
719
+ template: "<div class=\"auto-complete-container\">\n <input\n id=\"inputLocationSearch\"\n (input)=\"onInput()\"\n [formControl]=\"form.controls.searchTerm\"\n [matAutocomplete]=\"autoSearchLocation\"\n class=\"govuk-input\"\n [attr.disabled]=\"disabled\">\n <mat-autocomplete class=\"mat-autocomplete-panel-extend\" autoActiveFirstOption #autoSearchLocation=\"matAutocomplete\">\n <mat-option *ngFor=\"let location of locations\"\n (onSelectionChange)=\"onSelectionChange(location)\">\n {{ location.site_name }}\n </mat-option>\n <mat-option *ngIf=\"!locations.length && showAutocomplete && term && term.length >= this.minSearchCharacters\">No results found</mat-option>\n </mat-autocomplete>\n</div>\n",
720
+ styles: [".autocomplete__input--show-all-values{padding:5px 34px 5px 5px;cursor:pointer}.autocomplete__dropdown-arrow-down{z-index:-1;display:inline-block;position:absolute;right:8px;width:24px;height:24px;top:10px}.autocomplete__menu{background-color:#fff;border:2px solid #0b0c0c;border-top:0;color:#0b0c0c;margin:0;max-height:342px;overflow-x:hidden;padding:0;width:100%;width:calc(100% - 4px)}.autocomplete__menu--visible{display:block}.autocomplete__menu--hidden{display:none}.autocomplete__menu--overlay{box-shadow:0 2px 6px rgba(0,0,0,.256863);left:0;position:absolute;top:100%;z-index:100}.autocomplete__menu--inline{position:relative}.autocomplete__option{border-left-width:0;border-bottom:1px solid #b1b4b6;border-right-width:0;border-top-width:1px;cursor:pointer;display:block;position:relative}.autocomplete__option>*{pointer-events:none}.autocomplete__option:first-of-type{border-top-width:0}.autocomplete__option:last-of-type{border-bottom-width:0}.autocomplete__option--odd{background-color:#fafafa}.autocomplete__option--focused,.autocomplete__option:hover{background-color:#1d70b8;border-color:#1d70b8;color:#fff;outline:0}.autocomplete__option--no-results{background-color:#fafafa;color:#646b6f;cursor:not-allowed}.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.25}.autocomplete__hint,.autocomplete__option{padding:5px}@media (min-width:641px){.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.31579}}.div-action{display:inline-block}.add-location{display:inline}.remove-location-button{margin:5px}.hide-autocomplete{display:none}.auto-complete-container{min-width:550px;display:inline-block;margin-right:4px}.autocomplete__input{line-height:24px;font-size:19px}"]
721
+ },] }
722
+ ];
723
+ SearchLocationComponent.ctorParameters = () => [
724
+ { type: LocationService },
725
+ { type: SessionStorageService },
726
+ { type: FormBuilder },
727
+ { type: ChangeDetectorRef }
728
+ ];
729
+ SearchLocationComponent.propDecorators = {
730
+ control: [{ type: Input }],
731
+ disabled: [{ type: Input }],
732
+ singleMode: [{ type: Input }],
733
+ locationType: [{ type: Input }],
734
+ serviceIds: [{ type: Input }],
735
+ submitted: [{ type: Input }],
736
+ delay: [{ type: Input }],
737
+ form: [{ type: Input }],
738
+ showAutocomplete: [{ type: Input }],
739
+ locations: [{ type: Input }],
740
+ bookingCheck: [{ type: Input }],
741
+ locationSelected: [{ type: Output }],
742
+ locationInputChanged: [{ type: Output }],
743
+ searchLocationChanged: [{ type: Output }],
744
+ reset: [{ type: Input }],
745
+ selectedLocations: [{ type: Input }]
746
+ };
747
+
748
+ class FindLocationComponent {
749
+ constructor() {
750
+ this.locationFieldChanged = new EventEmitter();
751
+ this.selectedLocations = [];
752
+ this.submitted = true;
753
+ this.enableAddLocationButton = true;
754
+ this.locationTitle = 'Search for a location by name';
755
+ this.disableInputField = false;
756
+ this.locations = [];
757
+ this.tempSelectedLocation = null;
758
+ this.serviceIds = 'SSCS,IA';
759
+ this.pServices = [];
760
+ this.pDisabled = false;
603
761
  }
604
- toggleSelectAll(event, form, item, field) {
605
- const isChecked = event.target.checked;
606
- const formArray = form.get(field.name);
607
- if (!item.selectAll) {
608
- const allChecked = formArray.controls.every((control) => control.value);
609
- let index = null;
610
- const hasSelectAllOption = field.options.find((option, i) => {
611
- if (option.hasOwnProperty('selectAll')) {
612
- index = i;
613
- return true;
614
- }
615
- return false;
616
- });
617
- // tslint:disable-next-line:variable-name
618
- const isAllCheckedExcludingTheSelectAllOption = formArray.controls.filter((_control, i) => i !== index)
619
- .every((control) => control.value);
620
- if (!allChecked && hasSelectAllOption && !isChecked) {
621
- formArray.controls.forEach((control, i) => {
622
- if (index === i) {
623
- control.patchValue(false);
624
- return;
625
- }
626
- });
627
- }
628
- else if (hasSelectAllOption && !allChecked && isChecked && isAllCheckedExcludingTheSelectAllOption) {
629
- formArray.controls[index].patchValue(true);
630
- }
631
- return;
762
+ get disabled() {
763
+ return this.pDisabled;
764
+ }
765
+ set disabled(value) {
766
+ if (value) {
767
+ this.searchLocationComponent.resetSearchTerm();
768
+ this.removeSelectedValues();
632
769
  }
633
- formArray.controls.forEach((control) => {
634
- if (isChecked) {
635
- control.patchValue(true);
770
+ this.pDisabled = this.disableInputField === true ? true : null;
771
+ }
772
+ get services() {
773
+ return this.pServices;
774
+ }
775
+ set services(value) {
776
+ this.pServices = value;
777
+ const field = this.fields.find(f => f.name === this.field.findLocationField);
778
+ if (field) {
779
+ if (typeof value === 'string') {
780
+ this.serviceIds = value;
636
781
  }
637
782
  else {
638
- control.patchValue(false);
783
+ this.serviceIds = getValues(field.options, value).filter(x => x !== 'services_all').join(',');
639
784
  }
640
- });
785
+ }
641
786
  }
642
- resetField(resetField, form) {
643
- const control = form.get(resetField);
644
- const defaultValue = this.config.cancelSetting.fields.find((f) => f.name === resetField);
645
- if (control instanceof FormArray) {
646
- for (let i = 0; i < control.length; i++) {
647
- control.removeAt(i);
648
- }
787
+ ngOnInit() {
788
+ // implemented to get rid of undefined values
789
+ this.selectedLocations = this.selectedLocations.filter(location => location.epimms_id);
790
+ }
791
+ addLocation() {
792
+ if (this.tempSelectedLocation) {
793
+ this.selectedLocations = [...this.selectedLocations, this.tempSelectedLocation];
794
+ this.addSelectedLocationsToForm([this.tempSelectedLocation]);
795
+ this.tempSelectedLocation = null;
796
+ this.locations = [];
797
+ this.searchLocationComponent.resetSearchTerm();
649
798
  }
650
- else if (control instanceof FormGroup) {
651
- const keys = Object.keys(control.value);
652
- for (const key of keys) {
653
- this.resetField(key, control);
799
+ }
800
+ removeLocation(location) {
801
+ if (location.epimms_id) {
802
+ this.selectedLocations = this.selectedLocations.filter(selectedLocation => selectedLocation.epimms_id !== location.epimms_id);
803
+ const formArray = this.form.get(this.field.name);
804
+ const index = formArray.value.findIndex(selectedLocation => selectedLocation.epimms_id === location.epimms_id);
805
+ if (index > -1) {
806
+ formArray.removeAt(index);
654
807
  }
655
808
  }
656
- else if (control instanceof FormControl) {
657
- const value = defaultValue && defaultValue.value && defaultValue.value.length ? defaultValue.value[0] : null;
658
- control.setValue(value);
659
- }
660
809
  }
661
- mergeDefaultFields(filter) {
662
- if (filter) {
663
- filter.fields = this.filterService.get(this.config.id) ? this.filterService.get(this.config.id).fields : filter.fields;
664
- }
665
- else if (this.config && this.config.cancelSetting) {
666
- this._settings = {
667
- id: this.config.id,
668
- fields: JSON.parse(JSON.stringify(this.config.cancelSetting.fields))
669
- };
810
+ onInputChanged(term) {
811
+ // if the filter is in single mode clear the selected locations
812
+ if (typeof term === 'string' && this.field.maxSelected === 1) {
813
+ this.removeSelectedValues();
670
814
  }
671
815
  }
672
- getSettings() {
673
- this._settings = this.filterService.get(this.config.id);
816
+ onSearchInputChanged() {
817
+ this.locationFieldChanged.emit();
674
818
  }
675
- buildForm(config, settings, reset) {
676
- const findPersonControl = this.form ? this.form.get('findPersonControl') : null;
677
- this.form = this.fb.group({});
678
- if (findPersonControl) {
679
- // in order to maintain find person component, control needs to be kept
680
- this.form.addControl('findPersonControl', findPersonControl);
819
+ onLocationSelected(location) {
820
+ if (this.field.maxSelected === 1) {
821
+ this.removeSelectedValues();
822
+ this.addSelectedLocationsToForm([location]);
681
823
  }
682
- for (const field of config.fields) {
683
- if (field.type === 'checkbox' || field.type === 'checkbox-large') {
684
- const formArray = this.buildCheckBoxFormArray(field, settings);
685
- this.form.addControl(field.name, formArray);
686
- }
687
- else if (field.type === 'find-location') {
688
- const formArray = this.buildFindLocationFormArray(field, settings);
689
- this.form.addControl(field.name, formArray);
690
- }
691
- else {
692
- const validators = [];
693
- if (field.minSelected && field.minSelected > 0) {
694
- validators.push(Validators.required);
695
- }
696
- let defaultValue = null;
697
- if (reset && config.cancelSetting) {
698
- const cancelField = config.cancelSetting.fields.find((f) => f.name === field.name);
699
- defaultValue = cancelField && cancelField.value ? cancelField.value[0] : '';
700
- }
701
- else if (settings && settings.fields) {
702
- const lastSavedValue = settings.fields.find((f) => f.name === field.name);
703
- defaultValue = lastSavedValue && lastSavedValue ? lastSavedValue.value[0] : '';
704
- }
705
- // if field is find-person build a form group;
706
- if (field.type === 'find-person') {
707
- const formGroup = new FormGroup({
708
- domain: new FormControl(''),
709
- email: new FormControl(defaultValue && defaultValue.hasOwnProperty('email') ? defaultValue.email : '', validators),
710
- id: new FormControl(''),
711
- name: new FormControl(''),
712
- knownAs: new FormControl(''),
713
- });
714
- this.form.addControl(field.name, formGroup);
715
- }
716
- else {
717
- const control = new FormControl(defaultValue, validators);
718
- this.form.addControl(field.name, control);
719
- }
720
- // if field updates find person component set the initial domain
721
- if (field.findPersonField) {
722
- this.fieldChanged(field, this.form);
824
+ else {
825
+ if (!this.selectedLocations.find(x => x.epimms_id === location.epimms_id)) {
826
+ if (location.epimms_id) {
827
+ this.tempSelectedLocation = location;
723
828
  }
724
829
  }
725
830
  }
726
831
  }
727
- buildCheckBoxFormArray(field, settings) {
728
- const validators = GenericFilterComponent.addFormValidators(field);
729
- const formArray = this.fb.array([], validators);
730
- let defaultValues;
731
- if (settings && settings.fields) {
732
- defaultValues = settings.fields.find((f) => f.name === field.name);
733
- }
734
- for (const option of field.options) {
735
- let checked = false;
736
- if (defaultValues && Array.isArray(defaultValues.value)) {
737
- checked = !!defaultValues.value.find((value) => value === option.key);
738
- }
739
- formArray.push(new FormControl(checked));
832
+ removeSelectedValues() {
833
+ const formArray = this.form.get(this.field.name);
834
+ for (let i = 0; i < formArray.length; i++) {
835
+ formArray.removeAt(i);
740
836
  }
741
- return formArray;
837
+ this.selectedLocations = [];
742
838
  }
743
- buildFindLocationFormArray(field, settings) {
744
- const validators = GenericFilterComponent.addFormValidators(field);
745
- const formArray = this.fb.array([], validators);
746
- let defaultValues;
747
- if (settings && settings.fields) {
748
- defaultValues = settings.fields.find((f) => f.name === field.name);
749
- if (defaultValues && defaultValues.value && defaultValues.value.length > 0) {
750
- for (const defaultValue of defaultValues.value) {
751
- formArray.push(new FormControl(defaultValue));
752
- }
753
- }
754
- }
755
- return formArray;
756
- }
757
- getSelectedValues(formValues, config) {
758
- return Object.keys(formValues).map((name) => {
759
- const values = formValues[name];
760
- if (Array.isArray(values)) {
761
- const field = config.fields.find(f => f.name === name);
762
- if (field.type === 'find-location') {
763
- return { value: values, name };
764
- }
765
- else {
766
- return { value: getValues(field.options, values), name };
767
- }
768
- }
769
- else {
770
- return { value: [values], name };
771
- }
772
- });
773
- }
774
- emitFormErrors(form) {
775
- const errors = [];
776
- for (const field of this.config.fields) {
777
- const formGroup = form.get(field.name);
778
- if (formGroup && formGroup.errors && formGroup.errors.minLength) {
779
- errors.push({ name: field.name, error: field.minSelectedError });
780
- }
781
- if (formGroup && formGroup.errors && formGroup.errors.maxLength) {
782
- errors.push({ name: field.name, error: field.minSelectedError });
783
- }
784
- }
785
- if (errors.length) {
786
- this.filterService.givenErrors.next(errors);
839
+ addSelectedLocationsToForm(locations) {
840
+ const formArray = this.form.get(this.field.name);
841
+ for (const location of locations) {
842
+ formArray.push(new FormControl(location));
787
843
  }
788
844
  }
789
845
  }
790
- GenericFilterComponent.decorators = [
846
+ FindLocationComponent.decorators = [
791
847
  { type: Component, args: [{
792
- selector: 'xuilib-generic-filter',
793
- template: "<form [formGroup]=\"form\" (ngSubmit)=\"applyFilter(form)\">\n <div class=\"contain-classes\" *ngFor=\"let field of config.fields\">\n <hr *ngIf=\"field.lineBreakBefore\" class=\"govuk-section-break govuk-section-break--visible elevated-break\">\n <div class=\"govuk-form-group xui-generic-filter\"\n [hidden]=\"hidden(field, form)\"\n [id]=\"field.name\"\n [ngClass]=\"{'form-group-error': submitted && (form.get(field.name).errors?.minLength || form.get(field.name).errors?.maxLength)}\">\n <h3 *ngIf=\"field.title\" class=\"govuk-heading-s\">{{field.title}}</h3>\n <p class=\"govuk-body\" *ngIf=\"field.subTitle\">{{field.subTitle}}</p>\n <span [id]=\"field.name + '-error'\" class=\"govuk-error-message\" *ngIf=\"field.displayMinSelectedError && submitted && form.get(field.name).errors?.minLength\">\n <span class=\"govuk-visually-hidden\">Error:</span> {{field.minSelectedError}}\n </span>\n <span [id]=\"field.name + '-error'\" class=\"govuk-error-message\" *ngIf=\"field.displayMaxSelectedError && submitted && form.get(field.name).errors?.maxLength\">\n <span class=\"govuk-visually-hidden\">Error:</span> {{field.maxSelectedError}}\n </span>\n <div class=\"govuk-body\" [ngSwitch]=\"field.type\">\n <ng-container *ngSwitchCase=\"'select'\">\n <select class=\"govuk-select\" (change)=\"fieldChanged(field, form)\" [attr.disabled]=\"disabled(field, form)\" [name]=\"'select_' + field.name\" [id]=\"'select_' + field.name\" [formControlName]=\"field.name\">\n <option disabled selected hidden value=\"\">{{field.disabledText}}</option>\n <option class=\"govuk-radios__item\" *ngFor=\"let item of field.options\" [value]=\"item.key\">{{item.label}}</option>\n </select>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <div class=\"govuk-checkboxes govuk-checkboxes--small\" [formGroupName]=\"field.name\" [attr.field]=\"field.name\" [id]=\"'checkbox_' + field.name\">\n <div *ngFor=\"let item of field.options; let i = index\" class=\"govuk-checkboxes__item\">\n <input type=\"checkbox\" class=\"govuk-checkboxes__input\"\n [attr.disabled]=\"disabled(field, form)\"\n [formControlName]=\"i\"\n (change)=\"toggleSelectAll($event, form, item, field)\"\n [value]=\"item.key\" [id]=\"'checkbox_' + item.key\"\n [name]=\"'checkbox_' + item.key\"\n />\n <label\n [for]=\"'checkbox_' + item.key\"\n class=\"govuk-label govuk-checkboxes__label\"\n [ngClass]=\"{'govuk-!-font-weight-bold': item.selectAll}\"\n >{{item.label}}</label>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox-large'\">\n <div class=\"govuk-checkboxes\" [formGroupName]=\"field.name\" [attr.field]=\"field.name\" [id]=\"'checkbox_' + field.name\">\n <div *ngFor=\"let item of field.options; let i = index\" class=\"govuk-checkboxes__item\">\n <input type=\"checkbox\" class=\"govuk-checkboxes__input\"\n [attr.disabled]=\"disabled(field, form)\"\n [formControlName]=\"i\"\n (change)=\"toggleSelectAll($event, form, item, field)\"\n [value]=\"item.key\" [id]=\"'checkbox_' + item.key\"\n [name]=\"'checkbox_' + item.key\"\n />\n <label\n [for]=\"'checkbox_' + item.key\"\n class=\"govuk-label govuk-checkboxes__label\"\n [ngClass]=\"{'govuk-!-font-weight-bold': item.selectAll}\"\n >{{item.label}}</label>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'radio'\">\n <div class=\"govuk-radios\">\n <div *ngFor=\"let item of field.options\" class=\"govuk-radios__item\">\n <input type=\"radio\"\n [formControlName]=\"field.name\"\n [id]=\"'radio_' + item.key\"\n [attr.disabled]=\"disabled(field, form)\"\n [checked]=\"item.key === form.get(field.name).value\"\n class=\"govuk-radios__input\"\n [value]=\"item.key\"\n (change)=\"fieldChanged(field, form)\"\n />\n <label [for]=\"'radio_' + item.key\" class=\"govuk-label govuk-radios__label\">{{item.label}}</label>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'find-person'\">\n <xuilib-find-person subTitle=\"\" (personSelected)=\"updatePersonControls($event, field)\"\n (personFieldChanged)=\"inputChanged(field)\"\n [submitted]=\"submitted\"\n [disabled]=\"disabled(field, form)\"\n [domain]=\"form.get(field.domainField)?.value\"\n [findPersonGroup]=\"form\"\n [selectedPerson]=\"form.get(field.name)?.value?.email\"\n [userIncluded]=\"false\"\n ></xuilib-find-person>\n </ng-container>\n <ng-container *ngSwitchCase=\"'find-location'\">\n <xuilib-find-location (locationFieldChanged)=\"inputChanged(field)\"\n [form]=\"form\"\n [fields]=\"config.fields\"\n [locationTitle]=\"field.locationTitle\"\n [enableAddLocationButton]=\"field.enableAddLocationButton\"\n [disabled]=\"disabled(field, form)\"\n [disableInputField]=\"field.disable\"\n [selectedLocations]=\"form.get(field.name)?.value\"\n [submitted]=\"submitted\"\n [services]=\"form.get(field.findLocationField)?.value\"\n [field]=\"field\"\n ></xuilib-find-location>\n </ng-container>\n </div>\n </div>\n </div>\n <hr class=\"govuk-section-break govuk-section-break--m govuk-section-break--visible\"/>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-full\">\n <button\n class=\"govuk-button govuk-!-margin-right-1 govuk-!-margin-bottom-0\"\n type=\"submit\"\n id=\"applyFilter\"\n [disabled]=\"config.enableDisabledButton && form.invalid\"\n >{{config.applyButtonText || 'Apply'}}</button>\n <button *ngIf=\"config.showCancelFilterButton\"\n class=\"govuk-button govuk-button--secondary govuk-!-margin-bottom-0\"\n type=\"button\"\n id=\"cancelFilter\"\n (click)=\"cancelFilter()\">{{ config.cancelButtonText || 'Cancel'}}</button>\n </div>\n </div>\n</form>\n",
794
- changeDetection: ChangeDetectionStrategy.OnPush,
795
- encapsulation: ViewEncapsulation.None,
796
- styles: [".contain-classes .elevated-break{position:relative;top:-10px}.contain-classes .xui-generic-filter .select-all{margin-bottom:10px}.contain-classes .xui-generic-filter .govuk-checkboxes{display:flex;flex-wrap:wrap}.contain-classes .xui-generic-filter .govuk-checkboxes>div{flex-grow:1;flex-shrink:0}"]
848
+ selector: 'xuilib-find-location',
849
+ template: "<div class=\"location-picker-custom\">\n <div class=\"search-location\">\n <div>\n <label id=\"input-selected-location-label\" *ngIf=\"locationTitle\">{{locationTitle}}</label>\n </div>\n <exui-search-location class=\"search-location\"\n [locations]=\"locations\"\n [selectedLocations]=\"selectedLocations\"\n [singleMode]=\"field.maxSelected === 1\"\n [bookingCheck]=\"field.bookingCheckType\"\n [delay]=\"300\"\n [disabled]=\"disabled\"\n [serviceIds]=\"serviceIds\"\n (locationInputChanged)=\"onInputChanged($event)\"\n (locationSelected)=\"onLocationSelected($event)\"\n (searchLocationChanged)=\"onSearchInputChanged()\"\n [locationType]=\"'case-management'\"></exui-search-location>\n <a href=\"javascript:void(0)\" (click)=\"addLocation()\" class=\"govuk-button\" data-module=\"govuk-button\" *ngIf=\"enableAddLocationButton\">\n Add location\n </a>\n </div>\n <ul class=\"hmcts-filter-tags selection-container\" *ngIf=\"field.maxSelected != 1\">\n <li class=\"location-selection\" *ngFor=\"let selection of selectedLocations\">\n <a class=\"hmcts-filter__tag\" (click)=\"removeLocation(selection)\" href=\"javascript:void(0)\">\n {{ selection.site_name }}\n </a>\n </li>\n </ul>\n</div>\n",
850
+ styles: [""]
797
851
  },] }
798
852
  ];
799
- GenericFilterComponent.ctorParameters = () => [
800
- { type: FilterService },
801
- { type: FormBuilder }
802
- ];
803
- GenericFilterComponent.propDecorators = {
804
- config: [{ type: Input }],
805
- settings: [{ type: Input }]
853
+ FindLocationComponent.propDecorators = {
854
+ locationFieldChanged: [{ type: Output }],
855
+ selectedLocations: [{ type: Input }],
856
+ submitted: [{ type: Input }],
857
+ enableAddLocationButton: [{ type: Input }],
858
+ form: [{ type: Input }],
859
+ field: [{ type: Input }],
860
+ fields: [{ type: Input }],
861
+ locationTitle: [{ type: Input }],
862
+ disableInputField: [{ type: Input }],
863
+ searchLocationComponent: [{ type: ViewChild, args: [SearchLocationComponent, { static: true },] }],
864
+ disabled: [{ type: Input }],
865
+ services: [{ type: Input }]
806
866
  };
807
867
 
808
- /*
809
- * Gov UK Dialog Component
810
- * Responsible for displaying dialog layout
811
- * using ng-content to display content from parent
812
- * */
813
- class HmctsSessionDialogComponent {
814
- constructor() {
815
- this.close = new EventEmitter();
816
- }
817
- onClose() {
818
- this.close.emit();
819
- }
820
- }
821
- HmctsSessionDialogComponent.decorators = [
822
- { type: Component, args: [{
823
- selector: 'xuilib-session-dialog',
824
- template: "<div class=\"gem-c-modal-dialogue\" data-module=\"modal-dialogue\" id=\"modal-default\" style=\"display: block;\">\n <div class=\"gem-c-modal-dialogue__overlay\"></div>\n <dialog class=\"gem-c-modal-dialogue__box\" aria-modal=\"true\" role=\"dialog\" tabindex=\"0\" [ngStyle]=\"{'margin-top': positionTop}\">\n <div class=\"gem-c-modal-dialogue__header\">\n <svg role=\"presentation\" focusable=\"false\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 38 38\" height=\"33\" width=\"33\">\n <style type=\"text/css\">\n .st0{fill:#FFFFFF;}\n </style>\n <g id=\"_4_-_granular_components_warning_icon\" transform=\"translate(0.5 0.5)\">\n <g id=\"Warning_icon\" transform=\"translate(0)\">\n <path id=\"Exclusion_1\" class=\"st0\" d=\"M18.5,37.5c-5.04,0.01-9.88-1.99-13.44-5.57C1.49,28.38-0.51,23.54-0.5,18.5\n c-0.01-5.04,1.99-9.88,5.56-13.43C8.62,1.49,13.46-0.51,18.5-0.5c5.04-0.01,9.88,1.99,13.44,5.56c3.57,3.56,5.58,8.39,5.56,13.44\n c0.01,5.04-1.99,9.88-5.56,13.44C28.38,35.51,23.54,37.51,18.5,37.5z M18.52,24.29c-0.4,0-0.8,0.08-1.17,0.23\n c-0.36,0.15-0.69,0.37-0.97,0.64c-0.28,0.27-0.5,0.59-0.65,0.95c-0.16,0.36-0.24,0.76-0.23,1.15c0,0.4,0.08,0.8,0.23,1.17\n c0.15,0.36,0.37,0.68,0.65,0.96c0.28,0.27,0.61,0.49,0.97,0.64c0.37,0.16,0.77,0.24,1.17,0.24c0.4,0,0.79-0.08,1.15-0.24\n c0.35-0.15,0.67-0.37,0.95-0.64c0.27-0.27,0.49-0.6,0.64-0.96c0.16-0.37,0.24-0.77,0.23-1.17c0-0.4-0.08-0.79-0.23-1.15\n c-0.15-0.35-0.37-0.67-0.64-0.95c-0.27-0.27-0.6-0.49-0.95-0.64C19.31,24.37,18.92,24.29,18.52,24.29L18.52,24.29z M16.11,7.5\n l0.42,14.87h3.91L20.86,7.5H16.11z\"/>\n </g>\n </g>\n </svg>\n <div class=\"gem-c-modal-dialogue__title\">We are about to sign you out</div>\n </div>\n <div class=\"gem-c-modal-dialogue__content\">\n <ng-content></ng-content>\n </div>\n </dialog>\n</div>\n",
825
- styles: [".gem-c-modal-dialogue{display:none;z-index:1000;overflow-x:hidden;overflow-y:scroll;outline:0}.gem-c-modal-dialogue,.gem-c-modal-dialogue__box{position:fixed;top:0;left:0;width:100%;height:100%}.gem-c-modal-dialogue__box{display:block;background:#fff;right:0;bottom:0;margin:0;padding:0;overflow-y:auto;border:0;font-family:GDS Transport,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c}.gem-c-modal-dialogue__box:focus{outline:3px solid #fd0}@media print{.gem-c-modal-dialogue__box{font-family:sans-serif}}@media (min-width:40.0625em){.gem-c-modal-dialogue__box{font-size:1.1875rem;line-height:1.3157894737}}@media print{.gem-c-modal-dialogue__box{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.gem-c-modal-dialogue__box{position:relative;top:inherit;right:inherit;bottom:inherit;left:inherit;width:auto;max-width:640px;height:auto;margin:30px auto;border:2px solid #0b0c0c}}@media (min-width:40.0625em){.gem-c-modal-dialogue__box--wide{max-width:960px}}@media (min-width:40.0625em) and (max-width:64em){.gem-c-modal-dialogue__box--wide{margin:30px}}.gem-c-modal-dialogue__overlay{position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;opacity:.8;background:#0b0c0c;pointer-events:none;touch-action:none}@media screen{.gem-o-template--modal{overflow-y:inherit}}.gem-o-template__body--modal{overflow:hidden}.gem-o-template__body--blur .govuk-footer,.gem-o-template__body--blur .govuk-header,.gem-o-template__body--blur .govuk-main-wrapper,.gem-o-template__body--blur .govuk-phase-banner,.gem-o-template__body--blur .govuk-skip-link,.gem-o-template__body--blur .govuk-width-container .govuk-back-link{filter:blur(2px)}.govuk-warning-text__icon{margin:0 0 0 12px}.gem-c-modal-dialogue__header{padding:9px 15px 10px;color:#fff;background:#d4351d;display:flex}.gem-c-modal-dialogue__title{margin:5px 0 4px 12px}.gem-c-modal-dialogue__logotype-crown{fill:currentColor;vertical-align:middle}.gem-c-modal-dialogue__logotype-crown-fallback-image{width:30px;height:26px;border:0;vertical-align:middle}.gem-c-modal-dialogue__content{padding:15px;background:#fff}.gem-c-modal-dialogue__close-button{position:absolute;top:0;right:0;width:44px;height:44px;border:0;color:#fff;background:none;cursor:pointer;font-family:GDS Transport,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:1.5rem;line-height:1.3}@media print{.gem-c-modal-dialogue__close-button{font-family:sans-serif}}@media (min-width:40.0625em){.gem-c-modal-dialogue__close-button{font-size:2.25rem;line-height:1.3}}@media print{.gem-c-modal-dialogue__close-button{font-size:24pt;line-height:1.3}}@media (max-width:40.0525em){.gem-c-modal-dialogue__close-button{font-size:36px;line-height:1.3}}.gem-c-modal-dialogue__close-button:focus,.gem-c-modal-dialogue__close-button:hover{color:#0b0c0c;box-shadow:0 -2px #fd0,0 4px #0b0c0c;text-decoration:none;outline:none;background:#fd0}"]
826
- },] }
827
- ];
828
- HmctsSessionDialogComponent.ctorParameters = () => [];
829
- HmctsSessionDialogComponent.propDecorators = {
830
- positionTop: [{ type: Input }],
831
- close: [{ type: Output }]
868
+ const getAllCaseworkersFromServices = (caseworkersByService) => {
869
+ let allCaseworkers = [];
870
+ caseworkersByService.forEach(caseworkerListByService => {
871
+ allCaseworkers = allCaseworkers.concat(caseworkerListByService.caseworkers);
872
+ });
873
+ return allCaseworkers;
832
874
  };
833
-
834
- class InviteUserFormComponent {
835
- constructor() {
836
- this.submitForm = new EventEmitter();
837
- }
838
- set errorMessages(value) {
839
- this.isInvalid = value || {};
840
- }
841
- onSubmit() {
842
- this.submitForm.emit();
843
- }
844
- }
845
- InviteUserFormComponent.decorators = [
846
- { type: Component, args: [{
847
- selector: 'xuilib-invite-user-form',
848
- template: "\n<form [formGroup]=\"inviteUserForm\" (ngSubmit)=\"onSubmit()\" >\n\n <xuilib-gov-uk-input\n [config]=\"{label: 'First name', hint: 'Include all middle names.', name: 'firstName', id: 'firstName', type: 'text', classes: 'testClass'}\"\n [errorMessage]=\"isInvalid.firstName\"\n [group]=\"inviteUserForm\">\n </xuilib-gov-uk-input>\n\n <xuilib-gov-uk-input\n [config]=\"{label: 'Last name', name: 'lastName', id: 'lastName', type: 'text'}\"\n [errorMessage]=\"isInvalid.lastName\"\n [group]=\"inviteUserForm\">\n </xuilib-gov-uk-input>\n\n <xuilib-gov-uk-input\n [config]=\"{label: 'Email address', name: 'email', id: 'email', type: 'email'}\"\n [errorMessage]=\"isInvalid.email\"\n [group]=\"inviteUserForm\">\n </xuilib-gov-uk-input>\n\n <xuilib-invite-permission-form [inviteUserForm]=\"inviteUserForm\" [errorMessages]=\"isInvalid.roles\">\n </xuilib-invite-permission-form>\n\n <button type=\"submit\" class=\"govuk-button\">\n Send invitation\n </button>\n</form>\n"
849
- },] }
850
- ];
851
- InviteUserFormComponent.propDecorators = {
852
- submitForm: [{ type: Output }],
853
- inviteUserForm: [{ type: Input }],
854
- errorMessages: [{ type: Input }]
875
+ const getSessionStorageKeyForServiceId = (serviceId) => {
876
+ return `${serviceId}-caseworkers`;
855
877
  };
856
-
857
- class InviteUserPermissionComponent {
858
- constructor() {
859
- this.isPuiCaseManager = false;
860
- this.isPuiUserManager = false;
861
- this.isPuiOrganisationManager = false;
862
- this.isPuiFinanceManager = false;
878
+ const getCaseworkers = (serviceId, sessionStorageService) => {
879
+ const sessionKey = getSessionStorageKeyForServiceId(serviceId);
880
+ const value = sessionStorageService.getItem(sessionKey);
881
+ if (value) {
882
+ return JSON.parse(value);
863
883
  }
864
- }
865
- InviteUserPermissionComponent.decorators = [
866
- { type: Component, args: [{
867
- selector: 'xuilib-invite-permission-form',
868
- template: " <!--permissions -->\n <ng-container [formGroup]=\"inviteUserForm\">\n <xuilib-gov-uk-form-group-wrapper\n [config]=\"{hint: 'Choose what the user will be able to do. You can change this later.', legend: 'Permissions', key: 'roles'}\"\n [formGroupName]=\"'roles'\"\n [error]=\"errorMessages\">\n\n <div class=\"govuk-checkboxes\">\n <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiCaseManager\"\n [config]=\"{value: 'pui-case-manager', label: 'Manage Cases', name: 'roles', hint: 'View, create and progress cases.', focusOn: 'roles'}\">\n </xuilib-gov-checkbox>\n\n <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiUserManager\"\n [config]=\"{value: 'pui-user-manager', label: 'Manage Users', name: 'roles',\n hint: 'Invite users.'}\">\n </xuilib-gov-checkbox>\n\n <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiOrganisationManager\"\n [config]=\"{value: 'pui-organisation-manager', label: 'Manage Organisation', name: 'roles',\n hint: 'View organisation name and addresses.'}\">\n </xuilib-gov-checkbox>\n\n <!-- <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiFinanceManager\"\n [config]=\"{value: 'pui-finance-manager', label: 'Manage Payments', name: 'roles',\n hint: 'View account balances, available credit and transactions.'}\">\n </xuilib-gov-checkbox> -->\n </div>\n\n </xuilib-gov-uk-form-group-wrapper>\n</ng-container>"
869
- },] }
870
- ];
871
- InviteUserPermissionComponent.propDecorators = {
872
- inviteUserForm: [{ type: Input }],
873
- isPuiCaseManager: [{ type: Input }],
874
- isPuiUserManager: [{ type: Input }],
875
- isPuiOrganisationManager: [{ type: Input }],
876
- isPuiFinanceManager: [{ type: Input }],
877
- errorMessages: [{ type: Input }]
878
884
  };
879
-
880
- class LoadingSpinnerComponent {
881
- constructor() {
882
- this.loadingText = 'Loading';
883
- }
884
- }
885
- LoadingSpinnerComponent.decorators = [
886
- { type: Component, args: [{
887
- selector: 'xuilib-loading-spinner',
888
- template: "<div class=\"spinner-container\">\n <div class=\"spinner-inner-container\">\n <p>{{loadingText}}</p>\n <div class=\"spinner\" style=\"margin: auto;\"></div>\n </div>\n</div>\n",
889
- encapsulation: ViewEncapsulation.None,
890
- styles: [".spinner-container{position:fixed;top:0;left:0;height:100%;width:100%;display:flex;justify-content:center;align-items:center;background:hsla(0,0%,100%,.5);z-index:99}.spinner-container .spinner-inner-container p{text-align:center}.spinner-container .spinner-inner-container .spinner{border:10px solid #ddd;border-top-color:#000;border-radius:50%;width:40px;height:40px;-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}"]
891
- },] }
892
- ];
893
- LoadingSpinnerComponent.propDecorators = {
894
- loadingText: [{ type: Input }]
885
+ const setCaseworkers = (serviceId, caseworkers, sessionStorageService) => {
886
+ const sessionKey = getSessionStorageKeyForServiceId(serviceId);
887
+ sessionStorageService.setItem(sessionKey, JSON.stringify(caseworkers));
895
888
  };
896
889
 
897
- class CaseSharingStateService {
898
- constructor() {
899
- this.caseState = [];
900
- this.subject = new BehaviorSubject(this.caseState);
901
- }
902
- get state() {
903
- return this.subject.asObservable().pipe(distinctUntilChanged());
904
- }
905
- setCases(cases) {
906
- this.caseState = [];
907
- cases.forEach(aCase => {
908
- this.caseState.push({ caseId: aCase.caseId, caseTitle: aCase.caseTitle, caseTypeId: aCase.caseTypeId, roles: aCase.roles,
909
- sharedWith: aCase.sharedWith, pendingShares: aCase.pendingShares, pendingUnshares: aCase.pendingUnshares });
910
- });
911
- this.subject.next(this.caseState);
912
- }
913
- getCases() {
914
- return this.caseState;
890
+ class FindAPersonService {
891
+ constructor(http, sessionStorageService) {
892
+ this.http = http;
893
+ this.sessionStorageService = sessionStorageService;
915
894
  }
916
- requestShare(user) {
917
- const oldSharedCases = this.caseState.slice();
918
- const newSharedCases = [];
919
- for (const sharedCase of oldSharedCases) {
920
- if (!sharedCase.pendingShares) {
921
- sharedCase.pendingShares = [];
922
- }
923
- const newPendingShares = sharedCase.pendingShares.slice();
924
- if (!sharedCase.pendingUnshares) {
925
- sharedCase.pendingUnshares = [];
926
- }
927
- const newPendingUnshares = sharedCase.pendingUnshares.slice();
928
- if (!this.userHasAccess(sharedCase, user)) {
929
- if (!newPendingShares.some(u => u.email === user.email)) {
930
- newPendingShares.push(user);
931
- }
932
- }
933
- else {
934
- for (let u = 0, ul = newPendingUnshares.length; u < ul; u++) {
935
- if (newPendingUnshares[u].email === user.email) {
936
- newPendingUnshares.splice(u, 1);
937
- break;
938
- }
939
- }
940
- }
941
- const newSharedCase = Object.assign(Object.assign({}, sharedCase), { pendingUnshares: newPendingUnshares, pendingShares: newPendingShares });
942
- newSharedCases.push(newSharedCase);
895
+ find(searchOptions) {
896
+ const userInfoStr = this.sessionStorageService.getItem('userDetails');
897
+ if (userInfoStr && !searchOptions.userIncluded) {
898
+ const userInfo = JSON.parse(userInfoStr);
899
+ this.userId = userInfo.id ? userInfo.id : userInfo.uid;
943
900
  }
944
- this.subject.next(newSharedCases);
945
- return newSharedCases;
901
+ this.assignedUser = searchOptions.assignedUser ? searchOptions.assignedUser : null;
902
+ return this.http.post('/workallocation/findPerson', { searchOptions })
903
+ .pipe(map(judiciary => judiciary.filter(judge => !([this.assignedUser, this.userId].includes(judge.id)))));
946
904
  }
947
- requestUnshare(caseId, user) {
948
- const newSharedCases = [];
949
- for (const sharedCase of this.caseState) {
950
- if (sharedCase.caseId === caseId) {
951
- if (!sharedCase.pendingUnshares) {
952
- sharedCase.pendingUnshares = [];
953
- }
954
- const newPendingUnshares = sharedCase.pendingUnshares.slice();
955
- if (newPendingUnshares) {
956
- if (!newPendingUnshares.some(u => u.email === user.email)) {
957
- newPendingUnshares.push(user);
958
- }
959
- }
960
- else {
961
- newPendingUnshares.push(user);
962
- }
963
- const newSharedCase = Object.assign(Object.assign({}, sharedCase), { pendingUnshares: newPendingUnshares });
964
- newSharedCases.push(newSharedCase);
905
+ findCaseworkers(searchOptions) {
906
+ const userInfoStr = this.sessionStorageService.getItem('userDetails');
907
+ if (userInfoStr) {
908
+ const userInfo = JSON.parse(userInfoStr);
909
+ this.userId = userInfo.id ? userInfo.id : userInfo.uid;
910
+ }
911
+ this.assignedUser = searchOptions.assignedUser ? searchOptions.assignedUser : null;
912
+ const fullServices = searchOptions.services;
913
+ const storedServices = [];
914
+ const newServices = [];
915
+ const storedCaseworkersByService = [];
916
+ fullServices.forEach(serviceId => {
917
+ const serviceKey = getSessionStorageKeyForServiceId(serviceId);
918
+ if (this.sessionStorageService.getItem(serviceKey)) {
919
+ storedServices.push(serviceId);
920
+ storedCaseworkersByService.push({ service: serviceId, caseworkers: JSON.parse(this.sessionStorageService.getItem(serviceKey)) });
965
921
  }
966
922
  else {
967
- newSharedCases.push(sharedCase);
923
+ newServices.push(serviceId);
968
924
  }
925
+ });
926
+ // if all services are stored then return the stored caseworkers by service
927
+ if (storedServices.length === fullServices.length) {
928
+ const storedCaseworkers = getAllCaseworkersFromServices(storedCaseworkersByService);
929
+ return of(this.searchInCaseworkers(storedCaseworkers, searchOptions));
969
930
  }
970
- this.subject.next(newSharedCases);
971
- return;
931
+ // all serviceIds passed in as node layer getting used anyway and caseworkers also stored there
932
+ return this.http.post('/workallocation/retrieveCaseWorkersForServices', { fullServices }).pipe(tap(caseworkersByService => {
933
+ caseworkersByService.forEach(caseworkerListByService => {
934
+ // for any new service, ensure that they are then stored in the session
935
+ if (newServices.includes(caseworkerListByService.service)) {
936
+ setCaseworkers(caseworkerListByService.service, caseworkerListByService.caseworkers, this.sessionStorageService);
937
+ }
938
+ });
939
+ }), map(caseworkersByService => {
940
+ const givenCaseworkers = getAllCaseworkersFromServices(caseworkersByService);
941
+ return this.searchInCaseworkers(givenCaseworkers, searchOptions);
942
+ }));
972
943
  }
973
- requestCancel(caseId, user) {
974
- const newSharedCases = [];
975
- for (const sharedCase of this.caseState) {
976
- if (sharedCase.caseId === caseId) {
977
- if (!sharedCase.pendingUnshares) {
978
- sharedCase.pendingUnshares = [];
979
- }
980
- const newPendingUnshares = sharedCase.pendingUnshares.slice();
981
- for (let iPendingUnshares = 0; iPendingUnshares < newPendingUnshares.length; iPendingUnshares++) {
982
- if (newPendingUnshares[iPendingUnshares].email === user.email) {
983
- newPendingUnshares.splice(iPendingUnshares, 1);
984
- break;
985
- }
986
- }
987
- if (!sharedCase.pendingShares) {
988
- sharedCase.pendingShares = [];
989
- }
990
- const newPendingShares = sharedCase.pendingShares.slice();
991
- for (let iPendingShares = 0; iPendingShares < newPendingShares.length; iPendingShares++) {
992
- if (newPendingShares[iPendingShares].email === user.email) {
993
- newPendingShares.splice(iPendingShares, 1);
994
- break;
995
- }
996
- }
997
- const newSharedCase = Object.assign(Object.assign({}, sharedCase), { pendingUnshares: newPendingUnshares, pendingShares: newPendingShares });
998
- newSharedCases.push(newSharedCase);
999
- }
1000
- else {
1001
- newSharedCases.push(sharedCase);
944
+ mapCaseworkers(caseworkers, roleCategory) {
945
+ const people = [];
946
+ caseworkers.forEach((caseworker) => {
947
+ const thisPerson = {
948
+ email: caseworker.email,
949
+ name: `${caseworker.firstName} ${caseworker.lastName}`,
950
+ id: caseworker.idamId,
951
+ domain: caseworker.roleCategory === RoleCategory.CASEWORKER ? PersonRole.CASEWORKER : PersonRole.ADMIN,
952
+ };
953
+ if (caseworker.roleCategory === roleCategory || roleCategory === RoleCategory.ALL) {
954
+ people.push(thisPerson);
1002
955
  }
1003
- }
1004
- this.subject.next(newSharedCases);
1005
- return;
956
+ });
957
+ return people;
1006
958
  }
1007
- removeCase(caseId) {
1008
- for (let i = 0, l = this.caseState.length; i < l; i++) {
1009
- if (this.caseState[i].caseId === caseId) {
1010
- this.caseState.splice(i, 1);
1011
- this.subject.next(this.caseState);
1012
- return;
1013
- }
959
+ searchInCaseworkers(caseworkers, searchOptions) {
960
+ let roleCategory = RoleCategory.ALL;
961
+ if (!(searchOptions.userRole === PersonRole.ALL)) {
962
+ roleCategory = searchOptions.userRole === PersonRole.CASEWORKER ? RoleCategory.CASEWORKER : RoleCategory.ADMIN;
1014
963
  }
964
+ const searchTerm = searchOptions && searchOptions.searchTerm ? searchOptions.searchTerm.toLowerCase() : '';
965
+ const people = caseworkers ? this.mapCaseworkers(caseworkers, roleCategory) : [];
966
+ const finalPeopleList = people.filter(person => person && person.name && person.name.toLowerCase().includes(searchTerm));
967
+ return searchOptions.userIncluded ? finalPeopleList.filter(person => person && person.id !== this.assignedUser)
968
+ : finalPeopleList.filter(person => person && person.id !== this.userId && person.id !== this.assignedUser);
1015
969
  }
1016
- userHasAccess(c, user) {
1017
- if (!c.sharedWith) {
1018
- return false;
1019
- }
1020
- for (let i = 0, l = c.sharedWith.length; i < l; i++) {
1021
- if (c.sharedWith[i].email === user.email) {
1022
- return true;
1023
- }
1024
- }
1025
- return false;
970
+ searchJudicial(value, serviceId) {
971
+ return this.http.post('api/prd/judicial/getJudicialUsersSearch', { searchString: value, serviceCode: serviceId });
1026
972
  }
1027
973
  }
1028
- CaseSharingStateService.ɵprov = i0.ɵɵdefineInjectable({ factory: function CaseSharingStateService_Factory() { return new CaseSharingStateService(); }, token: CaseSharingStateService, providedIn: "root" });
1029
- CaseSharingStateService.decorators = [
974
+ FindAPersonService.caseworkersKey = 'caseworkers';
975
+ FindAPersonService.ɵprov = i0.ɵɵdefineInjectable({ factory: function FindAPersonService_Factory() { return new FindAPersonService(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(SessionStorageService)); }, token: FindAPersonService, providedIn: "root" });
976
+ FindAPersonService.decorators = [
1030
977
  { type: Injectable, args: [{
1031
978
  providedIn: 'root'
1032
979
  },] }
1033
980
  ];
1034
- CaseSharingStateService.ctorParameters = () => [];
981
+ FindAPersonService.ctorParameters = () => [
982
+ { type: HttpClient },
983
+ { type: SessionStorageService }
984
+ ];
1035
985
 
1036
- class SelectedCaseConfirmComponent {
1037
- constructor(stateService) {
1038
- this.stateService = stateService;
1039
- this.changeLink = '';
986
+ class FindPersonComponent {
987
+ constructor(findPersonService, cd) {
988
+ this.findPersonService = findPersonService;
989
+ this.cd = cd;
990
+ this.personSelected = new EventEmitter();
991
+ this.personFieldChanged = new EventEmitter();
992
+ this.boldTitle = 'Find the person';
993
+ this.subTitle = 'Type the name of the person and select them.';
994
+ this.domain = PersonRole.ALL;
995
+ this.findPersonGroup = new FormGroup({});
996
+ this.submitted = true;
997
+ this.userIncluded = false;
998
+ this.placeholderContent = '';
999
+ this.isNoResultsShown = true;
1000
+ this.showUpdatedColor = false;
1001
+ this.selectedPersons = [];
1002
+ this.errorMessage = 'You must select a name';
1003
+ this.idValue = '';
1004
+ this.services = ['IA'];
1005
+ this.disabled = null;
1006
+ this.showAutocomplete = false;
1007
+ this.filteredOptions = [];
1008
+ this.minSearchCharacters = 2;
1009
+ }
1010
+ ngOnDestroy() {
1011
+ if (this.sub) {
1012
+ this.sub.unsubscribe();
1013
+ }
1040
1014
  }
1041
1015
  ngOnInit() {
1042
- this.shareCases$ = this.stateService.state;
1043
- this.shareCases$.subscribe(shareCases => this.shareCases = shareCases);
1016
+ this.findPersonControl = new FormControl(this.selectedPerson);
1017
+ this.findPersonGroup.addControl('findPersonControl', this.findPersonControl);
1018
+ this.sub = this.findPersonControl.valueChanges.pipe(tap(() => this.showAutocomplete = false), tap(() => this.filteredOptions = []), debounceTime(300), tap((searchTerm) => typeof searchTerm === 'string' ? this.personSelected.emit(null) : void 0), filter((searchTerm) => searchTerm && searchTerm.length > this.minSearchCharacters), switchMap((searchTerm) => this.filter(searchTerm).pipe(tap(() => this.showAutocomplete = true), catchError(() => this.filteredOptions = [])))).subscribe((people) => {
1019
+ this.filteredOptions = people;
1020
+ this.cd.detectChanges();
1021
+ });
1044
1022
  }
1045
- trackByUserId(user) {
1046
- return user.idamId;
1023
+ filter(searchTerm) {
1024
+ const findJudicialPeople = this.findPersonService.find({ searchTerm, userRole: this.domain, services: this.services, userIncluded: this.userIncluded, assignedUser: this.assignedUser });
1025
+ const findCaseworkersOrAdmins = this.findPersonService.findCaseworkers({ searchTerm, userRole: this.domain, services: this.services, userIncluded: this.userIncluded, assignedUser: this.assignedUser });
1026
+ if (searchTerm && searchTerm.length > this.minSearchCharacters) {
1027
+ switch (this.domain) {
1028
+ case PersonRole.JUDICIAL: {
1029
+ return findJudicialPeople.pipe(map(persons => {
1030
+ const ids = this.selectedPersons.map(({ id }) => id);
1031
+ return persons.filter(({ id }) => !ids.includes(id));
1032
+ }));
1033
+ }
1034
+ case PersonRole.ALL: {
1035
+ return zip(findJudicialPeople, findCaseworkersOrAdmins).pipe(map(separatePeople => separatePeople[0].concat(separatePeople[1])));
1036
+ }
1037
+ case PersonRole.CASEWORKER:
1038
+ case PersonRole.ADMIN: {
1039
+ return findCaseworkersOrAdmins;
1040
+ }
1041
+ default: {
1042
+ return of([]);
1043
+ }
1044
+ }
1045
+ }
1046
+ return of([]);
1047
1047
  }
1048
- showUserAccessBlock() {
1049
- if (this.sharedCase.pendingShares && this.sharedCase.pendingShares.length > 0) {
1050
- return true;
1048
+ onSelectionChange(selectedPerson) {
1049
+ this.personSelected.emit(selectedPerson);
1050
+ this.findPersonControl.setValue(this.getDisplayName(selectedPerson), { emitEvent: false, onlySelf: true });
1051
+ }
1052
+ getDisplayName(selectedPerson) {
1053
+ if (!selectedPerson) {
1054
+ return '';
1051
1055
  }
1052
- return this.sharedCase.pendingUnshares && this.sharedCase.pendingUnshares.length > 0;
1056
+ if (selectedPerson.domain === PersonRole.JUDICIAL && selectedPerson.knownAs) {
1057
+ return `${selectedPerson.knownAs} (${selectedPerson.email})`;
1058
+ }
1059
+ return selectedPerson.email ? `${selectedPerson.name} (${selectedPerson.email})` : selectedPerson.name;
1060
+ }
1061
+ onInput() {
1062
+ this.personFieldChanged.emit();
1053
1063
  }
1054
1064
  }
1055
- SelectedCaseConfirmComponent.decorators = [
1065
+ FindPersonComponent.decorators = [
1056
1066
  { type: Component, args: [{
1057
- selector: 'xuilib-selected-case-confirm',
1058
- template: "<div id=\"user-access-block-{{ sharedCase.caseId }}\" *ngIf=\"showUserAccessBlock()\">\n <h2 class=\"govuk-heading-m case-share-confirm__title\">{{ sharedCase.caseTitle }}</h2>\n <div class=\"case-share-confirm__caption-area\">\n <div class=\"govuk-caption-m case-share-confirm__caption\">\n {{ sharedCase.caseId }}\n </div>\n <a [routerLink]=\"changeLink\" class=\"case-share-confirm__change-link govuk-link govuk-!-font-size-19\">Change</a>\n </div>\n <table class=\"govuk-table\">\n <thead class=\"govuk-table__head\">\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Name</th>\n <th class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Email address</th>\n <th class=\"govuk-table__header govuk-table-column-actions\" scope=\"col\">Actions</th>\n </tr>\n </thead>\n <tbody class=\"govuk-table__body\">\n <tr class=\"govuk-table__row\" *ngFor=\"let user of sharedCase.pendingShares; trackBy: trackByUserId\">\n <td class=\"govuk-table__cell\">{{ user.firstName + ' ' + user.lastName }}</td>\n <td class=\"govuk-table__cell\">{{ user.email }}</td>\n <td class=\"govuk-table__cell\">\n <span class=\"hmcts-badge\">To be added</span>\n </td>\n </tr>\n <tr class=\"govuk-table__row\" *ngFor=\"let user of sharedCase.pendingUnshares; trackBy: trackByUserId\">\n <td class=\"govuk-table__cell\">{{ user.firstName + ' ' + user.lastName }}</td>\n <td class=\"govuk-table__cell\">{{ user.email }}</td>\n <td class=\"govuk-table__cell\">\n <span class=\"hmcts-badge hmcts-badge--red\">to be removed</span>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n",
1059
- styles: [".case-share-confirm__title{margin-bottom:0}.case-share-confirm__caption-area{border-bottom:1px solid #b1b4b6;padding-bottom:10px;display:inline-block;width:100%;clear:both}.case-share-confirm__caption{float:left}.case-share-confirm__change-link{float:right}.govuk-table-column-header{width:45%}.govuk-table-column-actions{width:10%}"]
1067
+ selector: 'xuilib-find-person',
1068
+ template: "<h1 class=\"govuk-heading-l\" *ngIf=\"title && title.length\">\n <span class=\"govuk-caption-l\">{{title}}</span>\n {{boldTitle}}\n</h1>\n<div class=\"govuk-form-group\" [formGroup]=\"findPersonGroup\"\n [ngClass]=\"{'form-group-error': findPersonGroup.get('findPersonControl').invalid && submitted}\">\n <fieldset class=\"govuk-fieldset\" aria-describedby=\"sub-title-hint\">\n <div id=\"sub-title-hint\" class=\"govuk-hint\" *ngIf=\"subTitle && subTitle.length\">\n {{subTitle}}\n </div>\n <span id=\"validation-error\" class=\"govuk-error-message\" *ngIf=\"findPersonGroup && findPersonGroup.errors\">\n <span class=\"govuk-visually-hidden\">Error:</span>{{findPersonGroup.errors.error ? findPersonGroup.errors.error : errorMessage}}\n </span>\n <input id=\"inputSelectPerson{{idValue}}\" type=\"text\" aria-label=\"select a person\"\n formControlName=\"findPersonControl\"\n [matAutocomplete]=\"auto\"\n class=\"govuk-input govuk-!-width-one-third\"\n [placeholder]=\"placeholderContent\"\n [attr.disabled]=\"disabled\"\n (input)=\"onInput()\">\n <mat-autocomplete autoActiveFirstOption #auto=\"matAutocomplete\" (optionSelected)=\"onSelectionChange($event.option.value)\">\n <mat-option *ngFor=\"let option of filteredOptions\"\n [value]=\"option\"\n [ngClass]=\"{'hide-autocomplete': !showAutocomplete, 'select-option': showUpdatedColor}\">\n {{getDisplayName(option)}}\n </mat-option>\n <mat-option [ngClass]=\"{'select-option': showUpdatedColor}\" *ngIf=\"isNoResultsShown && !filteredOptions.length && showAutocomplete\">No results found</mat-option>\n </mat-autocomplete>\n </fieldset>\n</div>\n",
1069
+ styles: [".mat-option:hover{background:#2596be}.mat-option.select-option:hover{background:#1d70b8;color:#fff}.hide-autocomplete{display:none}"]
1060
1070
  },] }
1061
1071
  ];
1062
- SelectedCaseConfirmComponent.ctorParameters = () => [
1063
- { type: CaseSharingStateService }
1072
+ FindPersonComponent.ctorParameters = () => [
1073
+ { type: FindAPersonService },
1074
+ { type: ChangeDetectorRef }
1064
1075
  ];
1065
- SelectedCaseConfirmComponent.propDecorators = {
1066
- sharedCase: [{ type: Input }],
1067
- changeLink: [{ type: Input }]
1076
+ FindPersonComponent.propDecorators = {
1077
+ personSelected: [{ type: Output }],
1078
+ personFieldChanged: [{ type: Output }],
1079
+ title: [{ type: Input }],
1080
+ boldTitle: [{ type: Input }],
1081
+ subTitle: [{ type: Input }],
1082
+ domain: [{ type: Input }],
1083
+ findPersonGroup: [{ type: Input }],
1084
+ selectedPerson: [{ type: Input }],
1085
+ submitted: [{ type: Input }],
1086
+ userIncluded: [{ type: Input }],
1087
+ assignedUser: [{ type: Input }],
1088
+ placeholderContent: [{ type: Input }],
1089
+ isNoResultsShown: [{ type: Input }],
1090
+ showUpdatedColor: [{ type: Input }],
1091
+ selectedPersons: [{ type: Input }],
1092
+ errorMessage: [{ type: Input }],
1093
+ idValue: [{ type: Input }],
1094
+ services: [{ type: Input }],
1095
+ disabled: [{ type: Input }]
1068
1096
  };
1069
1097
 
1070
- class SelectedCaseListComponent {
1071
- constructor(stateService) {
1072
- this.stateService = stateService;
1073
- this.shareCases = [];
1074
- this.toConfirm = false;
1075
- this.changeLink = '';
1076
- this.unselect = new EventEmitter();
1077
- this.synchronizeStore = new EventEmitter();
1078
- }
1079
- ngOnInit() {
1080
- this.shareCases$ = this.stateService.state;
1081
- this.shareCases$.subscribe(shareCases => this.shareCases = shareCases);
1098
+ class FilterService {
1099
+ constructor() {
1100
+ this.givenErrors = new BehaviorSubject(null);
1101
+ this.isInitialSetting = false;
1102
+ this.filterSettings = {};
1103
+ this.streams = {};
1082
1104
  }
1083
- onUnselect(sharedCase) {
1084
- this.unselect.emit(sharedCase);
1105
+ persist(setting, persistence) {
1106
+ switch (persistence) {
1107
+ case 'local':
1108
+ this.persistLocal(setting);
1109
+ break;
1110
+ case 'session':
1111
+ this.persistSession(setting);
1112
+ break;
1113
+ default:
1114
+ break;
1115
+ }
1116
+ this.persistMemory(setting);
1117
+ this.updateStreams(setting);
1085
1118
  }
1086
- onSynchronizeStore(event) {
1087
- this.synchronizeStore.emit(event);
1119
+ get(id) {
1120
+ if (this.filterSettings[id]) {
1121
+ return this.filterSettings[id];
1122
+ }
1123
+ if (sessionStorage.getItem(id)) {
1124
+ return JSON.parse(window.sessionStorage.getItem(id));
1125
+ }
1126
+ if (localStorage.getItem(id)) {
1127
+ return JSON.parse(window.localStorage.getItem(id));
1128
+ }
1129
+ return null;
1088
1130
  }
1089
- trackByCaseId(sharedCase) {
1090
- return sharedCase.caseId;
1131
+ getStream(id) {
1132
+ if (!this.streams[id]) {
1133
+ this.streams[id] = new BehaviorSubject(this.get(id));
1134
+ }
1135
+ return this.streams[id].asObservable();
1136
+ }
1137
+ persistLocal(setting) {
1138
+ window.localStorage.setItem(setting.id, JSON.stringify(setting));
1139
+ }
1140
+ persistSession(setting) {
1141
+ window.sessionStorage.setItem(setting.id, JSON.stringify(setting));
1142
+ }
1143
+ persistMemory(setting) {
1144
+ this.filterSettings[setting.id] = setting;
1145
+ }
1146
+ updateStreams(setting) {
1147
+ if (this.streams[setting.id]) {
1148
+ this.streams[setting.id].next(setting);
1149
+ }
1091
1150
  }
1092
1151
  }
1093
- SelectedCaseListComponent.decorators = [
1094
- { type: Component, args: [{
1095
- selector: 'xuilib-selected-case-list',
1096
- template: "<ng-container *ngIf=\"!toConfirm\">\n <xuilib-selected-case\n *ngFor=\"let sharedCase of (shareCases$ | async); trackBy: trackByCaseId\"\n [sharedCase]=\"sharedCase\"\n [removeUserFromCaseToggleOn]=\"removeUserFromCaseToggleOn\"\n (unselect)=\"onUnselect($event)\"\n (synchronizeStore)=\"onSynchronizeStore($event)\"\n >\n </xuilib-selected-case>\n</ng-container>\n\n<ng-container *ngIf=\"toConfirm\">\n <xuilib-selected-case-confirm\n *ngFor=\"let sharedCase of (shareCases$ | async); trackBy: trackByCaseId\"\n [sharedCase]=\"sharedCase\"\n [changeLink]=\"changeLink\">\n </xuilib-selected-case-confirm>\n</ng-container>\n",
1097
- styles: [""]
1152
+ FilterService.ɵprov = i0.ɵɵdefineInjectable({ factory: function FilterService_Factory() { return new FilterService(); }, token: FilterService, providedIn: "root" });
1153
+ FilterService.decorators = [
1154
+ { type: Injectable, args: [{
1155
+ providedIn: 'root'
1098
1156
  },] }
1099
1157
  ];
1100
- SelectedCaseListComponent.ctorParameters = () => [
1101
- { type: CaseSharingStateService }
1102
- ];
1103
- SelectedCaseListComponent.propDecorators = {
1104
- shareCases$: [{ type: Input }],
1105
- removeUserFromCaseToggleOn: [{ type: Input }],
1106
- toConfirm: [{ type: Input }],
1107
- changeLink: [{ type: Input }],
1108
- unselect: [{ type: Output }],
1109
- synchronizeStore: [{ type: Output }]
1110
- };
1111
1158
 
1112
- class SelectedCaseComponent {
1113
- constructor(stateService) {
1114
- this.stateService = stateService;
1115
- this.opened = false;
1116
- this.unselect = new EventEmitter();
1117
- this.synchronizeStore = new EventEmitter();
1159
+ class GenericFilterComponent {
1160
+ constructor(filterService, fb) {
1161
+ this.filterService = filterService;
1162
+ this.fb = fb;
1163
+ this.submitted = false;
1118
1164
  }
1119
- ngOnInit() {
1120
- this.shareCases$ = this.stateService.state;
1121
- this.shareCases$.subscribe(shareCases => this.shareCases = shareCases);
1165
+ get config() {
1166
+ return this._config;
1122
1167
  }
1123
- ngOnChanges(changes) {
1124
- if (changes.sharedCase) {
1125
- const sharedWith = this.sharedCase.sharedWith ? this.sharedCase.sharedWith : [];
1126
- const pendingShares = this.sharedCase.pendingShares ? this.sharedCase.pendingShares : [];
1127
- this.combinedSortedShares = this.combineAndSortShares(sharedWith, pendingShares);
1168
+ set config(value) {
1169
+ this._config = Object.assign(Object.assign({}, value), { fields: value.fields.map(field => (Object.assign(Object.assign({}, field), { displayMinSelectedError: false, displayMaxSelectedError: false }))) });
1170
+ this._config = value;
1171
+ }
1172
+ get settings() {
1173
+ return this._settings;
1174
+ }
1175
+ set settings(value) {
1176
+ if (!value) {
1177
+ this.getSettings();
1178
+ }
1179
+ if (value && value.fields) {
1180
+ this.mergeDefaultFields(value);
1128
1181
  }
1182
+ this._settings = value;
1129
1183
  }
1130
- onUnselect() {
1131
- this.unselect.emit(this.sharedCase);
1184
+ static addFormValidators(field) {
1185
+ const validators = [];
1186
+ if (field && field.minSelected) {
1187
+ validators.push(minSelectedValidator(field.minSelected));
1188
+ }
1189
+ if (field && field.maxSelected) {
1190
+ validators.push(maxSelectedValidator(field.maxSelected));
1191
+ }
1192
+ return validators;
1132
1193
  }
1133
- onDeselect(c) {
1134
- this.unselect.emit(c);
1194
+ ngOnInit() {
1195
+ if (!this.settings) {
1196
+ this.getSettings();
1197
+ }
1198
+ this.mergeDefaultFields(this.settings);
1199
+ this.buildForm(this.config, this.settings);
1200
+ this.formSub = this.form.valueChanges.subscribe(() => this.submitted = false);
1135
1201
  }
1136
- trackByUserId(user) {
1137
- return user.idamId;
1202
+ ngOnDestroy() {
1203
+ if (this.formSub) {
1204
+ this.formSub.unsubscribe();
1205
+ }
1138
1206
  }
1139
- canRemove(caseId, user) {
1140
- return this.shareCases$.pipe(map(cases => {
1141
- if (this.removeUserFromCaseToggleOn) {
1142
- for (const aCase of cases) {
1143
- if (aCase.caseId === caseId) {
1144
- if (aCase.pendingUnshares && aCase.pendingUnshares.some(u => u.idamId === user.idamId)) {
1145
- return false;
1146
- }
1147
- if (aCase.sharedWith && aCase.sharedWith.some(u => u.idamId === user.idamId)) {
1148
- return true;
1149
- }
1150
- }
1207
+ hidden(field, form) {
1208
+ if (!field.showCondition) {
1209
+ return false;
1210
+ }
1211
+ if (typeof field.showCondition === 'string') {
1212
+ const control = form.get(field.name);
1213
+ const [name, value] = field.showCondition.split('=');
1214
+ if (form.value && form.value[name] === value) {
1215
+ if (field.type === 'find-person') {
1216
+ control.get('email').setValidators(Validators.required);
1217
+ control.get('email').updateValueAndValidity();
1218
+ }
1219
+ else {
1220
+ control.setValidators(Validators.required);
1221
+ control.updateValueAndValidity();
1151
1222
  }
1223
+ return false;
1152
1224
  }
1153
- return false;
1154
- }));
1155
- }
1156
- canCancel(caseId, user) {
1157
- return this.shareCases$.pipe(map(cases => {
1158
- for (const aCase of cases) {
1159
- if (aCase.caseId === caseId) {
1160
- if (aCase.pendingShares && aCase.pendingShares.some(u => u.idamId === user.idamId)) {
1161
- return true;
1162
- }
1163
- if (aCase.pendingUnshares && aCase.pendingUnshares.some(u => u.idamId === user.idamId)) {
1164
- return true;
1165
- }
1166
- return false;
1225
+ else {
1226
+ if (field.type === 'find-person') {
1227
+ control.get('email').clearValidators();
1228
+ control.get('email').updateValueAndValidity();
1229
+ }
1230
+ else {
1231
+ control.clearValidators();
1232
+ control.updateValueAndValidity();
1167
1233
  }
1168
1234
  }
1169
- }));
1235
+ }
1236
+ return true;
1170
1237
  }
1171
- isToBeRemoved(caseId, user) {
1172
- return this.shareCases$.pipe(map(cases => {
1173
- for (const aCase of cases) {
1174
- if (aCase.caseId === caseId) {
1175
- return aCase.pendingUnshares && aCase.pendingUnshares.some(u => u.idamId === user.idamId);
1238
+ disabled(field, form) {
1239
+ if (!field.enableCondition) {
1240
+ return null;
1241
+ }
1242
+ if (typeof field.enableCondition === 'string') {
1243
+ const control = form.get(field.name);
1244
+ const [name, value] = field.enableCondition.split('=');
1245
+ if (form.value && form.value[name] === value) {
1246
+ if (field.type === 'find-person') {
1247
+ control.get('email').setValidators(Validators.required);
1248
+ control.get('email').updateValueAndValidity();
1249
+ }
1250
+ else {
1251
+ control.setValidators(Validators.required);
1252
+ control.updateValueAndValidity();
1176
1253
  }
1254
+ return null;
1177
1255
  }
1178
- }));
1179
- }
1180
- isToBeAdded(caseId, user) {
1181
- return this.shareCases$.pipe(map(cases => {
1182
- for (const aCase of cases) {
1183
- if (aCase.caseId === caseId) {
1184
- return aCase.pendingShares && aCase.pendingShares.some(u => u.idamId === user.idamId);
1256
+ else {
1257
+ if (field.type === 'find-person') {
1258
+ control.get('email').clearValidators();
1259
+ control.get('email').updateValueAndValidity();
1260
+ }
1261
+ else {
1262
+ control.clearValidators();
1263
+ control.updateValueAndValidity();
1185
1264
  }
1186
1265
  }
1187
- }));
1188
- }
1189
- onRemove(user, sharedCase) {
1190
- this.stateService.requestUnshare(sharedCase.caseId, user);
1191
- this.synchronizeStore.emit(this.shareCases);
1192
- }
1193
- onCancel(user, sharedCase) {
1194
- this.stateService.requestCancel(sharedCase.caseId, user);
1195
- this.synchronizeStore.emit(this.shareCases);
1266
+ }
1267
+ // find-location is special case where need to reset textbox (by existing disabling functionality)
1268
+ // field.disable referred to component itself
1269
+ if (field.type === 'find-location') {
1270
+ return true;
1271
+ }
1272
+ // Note: field.disable decides whether to actually disable or not
1273
+ return field.disable ? field.disable : null;
1196
1274
  }
1197
- showNoUsersAccessInfo() {
1198
- // A user is added to a case
1199
- if (this.sharedCase.pendingShares) {
1200
- if (this.sharedCase.pendingShares.length > 0) {
1201
- return false;
1202
- }
1275
+ applyFilter(form) {
1276
+ this.submitted = true;
1277
+ form.markAsTouched();
1278
+ if (form.valid) {
1279
+ this._settings = {
1280
+ id: this.config.id,
1281
+ fields: this.getSelectedValues(form.value, this.config)
1282
+ };
1283
+ this.filterService.givenErrors.next(null);
1284
+ const settings = Object.assign(Object.assign({}, this.settings), { reset: false });
1285
+ this.filterService.persist(settings, this.config.persistence);
1203
1286
  }
1204
- // A case has 0 users with access to it
1205
- if (this.sharedCase.sharedWith) {
1206
- if (this.sharedCase.sharedWith.length === 0) {
1207
- return true;
1208
- }
1287
+ else {
1288
+ this.emitFormErrors(form);
1209
1289
  }
1210
- // Access to the last user is removed
1211
- if (this.sharedCase.sharedWith && this.sharedCase.pendingUnshares) {
1212
- if (this.sharedCase.pendingUnshares.length > 0
1213
- && this.sharedCase.sharedWith.length === this.sharedCase.pendingUnshares.length) {
1214
- return true;
1290
+ }
1291
+ // when domain changes ensure that person field is reset
1292
+ fieldChanged(field, form) {
1293
+ // TODO - Do similar with jurisdiction/service for caseworkers by services
1294
+ if (field.changeResetFields && field.changeResetFields.length) {
1295
+ for (const resetField of field.changeResetFields) {
1296
+ this.resetField(resetField, form);
1215
1297
  }
1216
1298
  }
1217
- return false;
1218
1299
  }
1219
- showUserHasAccessInfo() {
1220
- return !this.showNoUsersAccessInfo();
1300
+ // when user enters input change radio button
1301
+ inputChanged(field) {
1302
+ if (field.radioSelectionChange && typeof field.radioSelectionChange === 'string') {
1303
+ const [name, value] = field.enableCondition.split('=');
1304
+ this.form.get(name).patchValue(value);
1305
+ }
1221
1306
  }
1222
- showUserAccessTable() {
1223
- if (this.sharedCase.pendingShares) {
1224
- if (this.sharedCase.pendingShares.length > 0) {
1225
- return true;
1226
- }
1307
+ cancelFilter() {
1308
+ this.buildForm(this.config, this.settings, true);
1309
+ if (this.config && this.config.cancelSetting) {
1310
+ this._settings.fields = JSON.parse(JSON.stringify(this.config.cancelSetting.fields));
1227
1311
  }
1228
- if (this.sharedCase.sharedWith) {
1229
- if (this.sharedCase.sharedWith.length > 0) {
1230
- return true;
1312
+ const settings = Object.assign(Object.assign({}, this.settings), { reset: true });
1313
+ this.filterService.persist(settings, this.config.persistence);
1314
+ this.filterService.givenErrors.next(null);
1315
+ this.submitted = false;
1316
+ }
1317
+ updatePersonControls(values, field) {
1318
+ let keys;
1319
+ if (!values) {
1320
+ keys = Object.keys(this.form.get(field.name).value);
1321
+ }
1322
+ else {
1323
+ keys = Object.keys(values);
1324
+ }
1325
+ for (const key of keys) {
1326
+ if (this.form.get(field.name) && this.form.get(field.name).get(key)) {
1327
+ const value = values && values[key] ? values[key] : null;
1328
+ this.form.get(field.name).get(key).patchValue(value);
1231
1329
  }
1232
1330
  }
1233
- return false;
1234
- }
1235
- combineAndSortShares(sharedWith, pendingShares) {
1236
- return [
1237
- ...sharedWith,
1238
- ...pendingShares
1239
- ].sort((user1, user2) => {
1240
- return user1.firstName.toLowerCase() > user2.firstName.toLowerCase() ? 1 : (user2.firstName.toLowerCase() > user1.firstName.toLowerCase() ? -1 : 0);
1241
- });
1242
- }
1243
- userIdSetter(isPending, id) {
1244
- return isPending ? `pendingShares-${id}` : `${id}`;
1245
- }
1246
- buildElementId(elementName) {
1247
- return `${elementName}-${this.sharedCase.caseId}`;
1248
- }
1249
- }
1250
- SelectedCaseComponent.decorators = [
1251
- { type: Component, args: [{
1252
- selector: 'xuilib-selected-case',
1253
- template: "<div id=\"{{buildElementId('govuk-accordion__section')}}\" class=\"govuk-accordion__section\">\n <div class=\"govuk-grid-row govuk-case-header\">\n <div class=\"govuk-grid-column-three-quarters\">\n <h3 id=\"{{buildElementId('case-title')}}\" class=\"govuk-case-title\">{{ sharedCase.caseTitle }}</h3>\n <h1 id=\"{{buildElementId('case-id')}}\" class=\"govuk-case-sub-title\">{{ sharedCase.caseId }}</h1>\n </div>\n <div class=\"govuk-grid-column-twenty-percent\">\n <button id=\"{{buildElementId('btn-deselect-case')}}\" class=\"govuk-button hmcts-button--secondary\" (click)=\"onDeselect(sharedCase)\" title=\"Deselect case\">Deselect case</button>\n </div>\n <div class=\"govuk-accordion__section-header govuk-grid-column-five-percent\">\n <div class=\"govuk-accordion__section-heading\">\n <button type=\"button\" id=\"{{buildElementId('accordion-with-summary-sections-heading')}}\"\n aria-controls=\"accordion-with-summary-sections-content-1\" class=\"govuk-accordion__section-button\"\n aria-describedby=\"accordion-with-summary-sections-summary-1\" aria-expanded=\"false\" title=\"Expand or Collapse\">\n <span class=\"govuk-accordion__icon\" aria-hidden=\"true\"></span></button>\n </div>\n </div>\n </div>\n <div id=\"{{buildElementId('accordion-with-summary-sections-content')}}\" class=\"govuk-accordion__section-content\"\n aria-labelledby=\"buildElementId('accordion-with-summary-sections-heading')\" >\n <div class=\"govuk-grid-row\" *ngIf=\"showNoUsersAccessInfo()\">\n <span id=\"{{buildElementId('access-info-no-user')}}\" class=\"govuk-div-align-left\">No users from your organisation currently have access to this case.</span>\n </div>\n <div class=\"govuk-grid-row\" *ngIf=\"showUserHasAccessInfo()\">\n <span id=\"{{buildElementId('access-info-has-users')}}\" class=\"govuk-div-align-left\">Users from your organisation with access to this case.</span>\n </div>\n <table class=\"govuk-table\" *ngIf=\"showUserAccessTable()\">\n <thead class=\"govuk-table__head\">\n <tr class=\"govuk-table__row\">\n <th id=\"{{buildElementId('name-heading')}}\" class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Name</th>\n <th id=\"{{buildElementId('email-heading')}}\" class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Email address</th>\n <th id=\"{{buildElementId('action-heading')}}\" class=\"govuk-table__header govuk-table-column-actions\" scope=\"col\">Actions</th>\n <th id=\"{{buildElementId('label-heading')}}\" class=\"govuk-table__header govuk-table-column-label\" scope=\"col\">&nbsp;&nbsp;</th>\n </tr>\n </thead>\n <tbody class=\"govuk-table__body\">\n <tr class=\"govuk-table__row\" *ngFor=\"let user of combinedSortedShares; index as idx; trackBy: trackByUserId\">\n <td id=\"user-full-name-{{ userIdSetter(canCancel(sharedCase.caseId, user) | async, idx) }}\" class=\"govuk-table__cell\">{{ user.firstName + ' ' + user.lastName }}</td>\n <td id=\"user-email-{{ userIdSetter(canCancel(sharedCase.caseId, user) | async, idx) }}\" class=\"govuk-table__cell\">{{ user.email }}</td>\n <td class=\"govuk-table__cell\">\n <a *ngIf=\"canRemove(sharedCase.caseId, user) | async\" (click)=\"onRemove(user, sharedCase)\" href=\"javascript:void(0);\">Remove <span class=\"govuk-visually-hidden\">{{ user.firstName + ' ' + user.lastName }} from case</span></a>\n <a *ngIf=\"canCancel(sharedCase.caseId, user) | async\" (click)=\"onCancel(user, sharedCase)\" href=\"javascript:void(0);\">Cancel <span class=\"govuk-visually-hidden\">adding {{ user.firstName + ' ' + user.lastName }} to case</span></a>\n </td>\n <td class=\"govuk-table__cell\">\n <span *ngIf=\"isToBeRemoved(sharedCase.caseId, user) | async\" class=\"hmcts-badge hmcts-badge--red\">To be removed</span>\n <span *ngIf=\"isToBeAdded(sharedCase.caseId, user) | async\" class=\"hmcts-badge\">To be added</span>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n",
1254
- styles: [".govuk-case-header{border-top:1px solid #bfc1c3}.govuk-case-title{font-size:24px;color:#005ea5;font-weight:700}.govuk-case-sub-title,.govuk-case-title{font-family:nta,Arial,sans-serif;padding-left:0}.govuk-case-sub-title{font-size:1rem!important;color:#6f777b;font-weight:400}.govuk-grid-row{margin-left:0;margin-right:0}.govuk-grid-column-three-quarters{padding-top:5px;padding-left:0}.govuk-grid-column-twenty-percent{box-sizing:border-box;padding-top:10px;width:20%;float:left}.govuk-grid-column-five-percent{box-sizing:border-box;padding-top:15px;width:5%;float:left}.govuk-table-column-header{width:40%}.govuk-table-column-actions,.govuk-table-column-label{width:10%}.govuk-div-align-left{font-family:nta,Arial,sans-serif;font-size:1.1875rem!important;line-height:1.31579!important;text-align:left;margin-bottom:20px;padding-left:0;color:#0b0c0c}.govuk-accordion__section-header{border-top:0}.govuk-accordion__section-content{padding-top:0}"]
1255
- },] }
1256
- ];
1257
- SelectedCaseComponent.ctorParameters = () => [
1258
- { type: CaseSharingStateService }
1259
- ];
1260
- SelectedCaseComponent.propDecorators = {
1261
- sharedCase: [{ type: Input }],
1262
- selectedUser: [{ type: Input }],
1263
- opened: [{ type: Input }],
1264
- removeUserFromCaseToggleOn: [{ type: Input }],
1265
- unselect: [{ type: Output }],
1266
- synchronizeStore: [{ type: Output }]
1267
- };
1268
-
1269
- class ServiceMessageComponent {
1270
- constructor() {
1271
- this.hideMessage = new EventEmitter();
1272
- }
1273
- onHideMessageEvent(key) {
1274
- this.hideMessage.emit(key);
1275
- }
1276
- }
1277
- ServiceMessageComponent.decorators = [
1278
- { type: Component, args: [{
1279
- selector: 'xuilib-service-message',
1280
- template: "<div class=\"hmcts-banner hmcts-banner--warning\">\n\n <svg class=\"hmcts-banner__icon\" fill=\"currentColor\" role=\"presentation\" focusable=\"false\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 25 25\" height=\"25\" width=\"25\">\n <path d=\"M13.6,15.4h-2.3v-4.5h2.3V15.4z M13.6,19.8h-2.3v-2.2h2.3V19.8z M0,23.2h25L12.5,2L0,23.2z\" />\n </svg>\n\n <div class=\"hmcts-banner__message\">\n <span class=\"hmcts-banner__assistive\">Warning</span>\n <h2 class=\"govuk-heading-s\" [innerHTML]=\"message\"></h2>\n <a [routerLink]=\"\" class=\"govuk-link--no-visited-state\" (click)=\"onHideMessageEvent(key)\">Hide message</a>\n </div>\n\n</div>"
1281
- },] }
1282
- ];
1283
- ServiceMessageComponent.ctorParameters = () => [];
1284
- ServiceMessageComponent.propDecorators = {
1285
- message: [{ type: Input }],
1286
- key: [{ type: Input }],
1287
- hideMessage: [{ type: Output }]
1288
- };
1289
-
1290
- class FeatureToggleService {
1291
- // tslint:disable-next-line: variable-name
1292
- initialize(_user, _clientId) {
1293
- throw new Error('Not implemented');
1294
1331
  }
1295
- // tslint:disable-next-line: variable-name
1296
- isEnabled(_feature) {
1297
- throw new Error('Not implemented');
1298
- }
1299
- // tslint:disable-next-line: variable-name
1300
- getValue(_key, _defaultValue) {
1301
- throw new Error('Not implemented');
1302
- }
1303
- // tslint:disable-next-line: variable-name
1304
- getValueOnce(_key, _defaultValue) {
1305
- throw new Error('Not implemented');
1306
- }
1307
- }
1308
- FeatureToggleService.ɵprov = i0.ɵɵdefineInjectable({ factory: function FeatureToggleService_Factory() { return new FeatureToggleService(); }, token: FeatureToggleService, providedIn: "root" });
1309
- FeatureToggleService.decorators = [
1310
- { type: Injectable, args: [{
1311
- providedIn: 'root'
1312
- },] }
1313
- ];
1314
-
1315
- class ServiceMessagesComponent {
1316
- constructor(featureToggleService) {
1317
- this.featureToggleService = featureToggleService;
1318
- this.filteredMessages = new Map();
1319
- }
1320
- ngOnInit() {
1321
- this.getServiceMessages();
1322
- }
1323
- getServiceMessages() {
1324
- this.featureToggleService.getValue(this.featureToggleKey, null)
1325
- .subscribe(messages => {
1326
- if (!!messages) {
1327
- this.createFilteredMessages(messages);
1332
+ toggleSelectAll(event, form, item, field) {
1333
+ const isChecked = event.target.checked;
1334
+ const formArray = form.get(field.name);
1335
+ if (!item.selectAll) {
1336
+ const allChecked = formArray.controls.every((control) => control.value);
1337
+ let index = null;
1338
+ const hasSelectAllOption = field.options.find((option, i) => {
1339
+ if (option.hasOwnProperty('selectAll')) {
1340
+ index = i;
1341
+ return true;
1342
+ }
1343
+ return false;
1344
+ });
1345
+ // tslint:disable-next-line:variable-name
1346
+ const isAllCheckedExcludingTheSelectAllOption = formArray.controls.filter((_control, i) => i !== index)
1347
+ .every((control) => control.value);
1348
+ if (!allChecked && hasSelectAllOption && !isChecked) {
1349
+ formArray.controls.forEach((control, i) => {
1350
+ if (index === i) {
1351
+ control.patchValue(false);
1352
+ return;
1353
+ }
1354
+ });
1328
1355
  }
1329
- });
1330
- }
1331
- createFilteredMessages(messages) {
1332
- this.hiddenBanners = JSON.parse(window.sessionStorage.getItem(this.serviceMessageCookie)) || [];
1333
- Object.keys(messages).forEach(key => {
1334
- const regEx = new RegExp(key);
1335
- if (this.userRoles.some(e => regEx.test(e)) && this.hiddenBanners.indexOf(key) === -1) {
1336
- this.filteredMessages.set(key, messages[key]);
1356
+ else if (hasSelectAllOption && !allChecked && isChecked && isAllCheckedExcludingTheSelectAllOption) {
1357
+ formArray.controls[index].patchValue(true);
1337
1358
  }
1338
- });
1339
- }
1340
- hideMessage(key) {
1341
- this.filteredMessages.delete(key);
1342
- this.hiddenBanners.push(key);
1343
- window.sessionStorage.setItem(this.serviceMessageCookie, JSON.stringify(this.hiddenBanners));
1344
- }
1345
- }
1346
- ServiceMessagesComponent.decorators = [
1347
- { type: Component, args: [{
1348
- selector: 'xuilib-service-messages',
1349
- template: "<div *ngIf=\"filteredMessages?.size > 0\" class=\"govuk-width-container govuk-!-margin-top-6\">\n <xuilib-service-message *ngFor=\"let message of filteredMessages | keyvalue\" [key]=\"message.key\"\n [message]=\"message.value\" (hideMessage)=\"hideMessage($event)\"></xuilib-service-message>\n</div>"
1350
- },] }
1351
- ];
1352
- ServiceMessagesComponent.ctorParameters = () => [
1353
- { type: FeatureToggleService }
1354
- ];
1355
- ServiceMessagesComponent.propDecorators = {
1356
- userRoles: [{ type: Input }],
1357
- featureToggleKey: [{ type: Input }],
1358
- serviceMessageCookie: [{ type: Input }]
1359
- };
1360
-
1361
- class ShareCaseConfirmComponent {
1362
- constructor(stateService) {
1363
- this.stateService = stateService;
1364
- this.shareCases = []; // cases selected for sharing
1365
- this.changeLink = '';
1366
- this.completeLink = '';
1367
- }
1368
- ngOnInit() {
1369
- this.shareCases$.subscribe(shareCases => {
1370
- this.shareCases = shareCases;
1371
- this.stateService.setCases(shareCases);
1372
- });
1373
- this.shareCases$ = this.stateService.state;
1374
- }
1375
- }
1376
- ShareCaseConfirmComponent.decorators = [
1377
- { type: Component, args: [{
1378
- selector: 'xuilib-share-case-confirm',
1379
- template: "<div id=\"casesToConfirm\">\n <h3 class=\"govuk-heading-l\">Cases</h3>\n <div *ngIf=\"shareCases && shareCases.length > 0\" id=\"summarySections\">\n <xuilib-selected-case-list\n [shareCases$]=\"shareCases$\"\n [toConfirm]=\"true\"\n [changeLink]=\"changeLink\">\n </xuilib-selected-case-list>\n </div>\n\n <div id=\"noCaseDisplay\" *ngIf=\"shareCases && shareCases.length === 0\" class=\"govuk-hint\">\n No cases to display.\n </div>\n\n</div>\n\n<div id=\"share-case-nav\" *ngIf=\"shareCases && shareCases.length > 0\">\n <button class=\"govuk-button\" title=\"Confirm\" [routerLink]=\"completeLink\">Confirm</button>\n</div>\n",
1380
- styles: [""]
1381
- },] }
1382
- ];
1383
- ShareCaseConfirmComponent.ctorParameters = () => [
1384
- { type: CaseSharingStateService }
1385
- ];
1386
- ShareCaseConfirmComponent.propDecorators = {
1387
- shareCases$: [{ type: Input }],
1388
- changeLink: [{ type: Input }],
1389
- completeLink: [{ type: Input }]
1390
- };
1391
-
1392
- class UserSelectComponent {
1393
- constructor() {
1394
- this.selected = new EventEmitter();
1395
- this.control = new FormControl();
1396
- }
1397
- ngOnInit() {
1398
- this.filteredUsers = this.control.valueChanges.pipe(map(value => typeof value === typeof 'string' ? this.filterUsers(value) : this.users));
1399
- this.selected.emit(null);
1400
- }
1401
- displayValue(user) {
1402
- return user ? `${user.firstName} ${user.lastName} - ${user.email}` : '';
1403
- }
1404
- onSelected(e) {
1405
- this.selected.emit(e.option.value);
1359
+ }
1360
+ else {
1361
+ formArray.controls.forEach((control) => {
1362
+ if (isChecked) {
1363
+ control.patchValue(true);
1364
+ }
1365
+ else {
1366
+ control.patchValue(false);
1367
+ }
1368
+ });
1369
+ }
1370
+ if (field.changeResetFields && field.changeResetFields.length) {
1371
+ for (const resetField of field.changeResetFields) {
1372
+ this.resetField(resetField, form);
1373
+ }
1374
+ }
1406
1375
  }
1407
- clear() {
1408
- this.control.setValue(null);
1376
+ resetField(resetField, form) {
1377
+ const control = form.get(resetField);
1378
+ const defaultValue = this.config.cancelSetting.fields.find((f) => f.name === resetField);
1379
+ if (control instanceof FormArray) {
1380
+ for (let i = 0; i < control.length; i++) {
1381
+ control.removeAt(i);
1382
+ }
1383
+ }
1384
+ else if (control instanceof FormGroup) {
1385
+ const keys = Object.keys(control.value);
1386
+ for (const key of keys) {
1387
+ this.resetField(key, control);
1388
+ }
1389
+ }
1390
+ else if (control instanceof FormControl) {
1391
+ const value = defaultValue && defaultValue.value && defaultValue.value.length ? defaultValue.value[0] : null;
1392
+ control.setValue(value);
1393
+ }
1409
1394
  }
1410
- onUserChange(newUserValue) {
1411
- if (!newUserValue || !newUserValue.email) {
1412
- this.selected.emit(null);
1395
+ mergeDefaultFields(filter) {
1396
+ if (filter) {
1397
+ filter.fields = this.filterService.get(this.config.id) ? this.filterService.get(this.config.id).fields : filter.fields;
1398
+ }
1399
+ else if (this.config && this.config.cancelSetting) {
1400
+ this._settings = {
1401
+ id: this.config.id,
1402
+ fields: JSON.parse(JSON.stringify(this.config.cancelSetting.fields))
1403
+ };
1413
1404
  }
1414
1405
  }
1415
- filterUsers(value) {
1416
- if (value) {
1417
- value = value.toLowerCase();
1418
- return this.users.filter(user => {
1419
- if (user.firstName.toLowerCase().includes(value)) {
1420
- return true;
1406
+ getSettings() {
1407
+ this._settings = this.filterService.get(this.config.id);
1408
+ }
1409
+ buildForm(config, settings, reset) {
1410
+ const findPersonControl = this.form ? this.form.get('findPersonControl') : null;
1411
+ this.form = this.fb.group({});
1412
+ if (findPersonControl) {
1413
+ // in order to maintain find person component, control needs to be kept
1414
+ this.form.addControl('findPersonControl', findPersonControl);
1415
+ }
1416
+ for (const field of config.fields) {
1417
+ if (field.type === 'checkbox' || field.type === 'checkbox-large') {
1418
+ const formArray = this.buildCheckBoxFormArray(field, settings);
1419
+ this.form.addControl(field.name, formArray);
1420
+ }
1421
+ else if (field.type === 'find-location') {
1422
+ const formArray = this.buildFindLocationFormArray(field, settings);
1423
+ this.form.addControl(field.name, formArray);
1424
+ }
1425
+ else {
1426
+ const validators = [];
1427
+ if (field.minSelected && field.minSelected > 0) {
1428
+ validators.push(Validators.required);
1421
1429
  }
1422
- if (user.lastName.toLowerCase().includes(value)) {
1423
- return true;
1430
+ let defaultValue = null;
1431
+ if (reset && config.cancelSetting) {
1432
+ const cancelField = config.cancelSetting.fields.find((f) => f.name === field.name);
1433
+ defaultValue = cancelField && cancelField.value ? cancelField.value[0] : '';
1424
1434
  }
1425
- if (user.email.toLowerCase().includes(value)) {
1426
- return true;
1435
+ else if (settings && settings.fields) {
1436
+ const lastSavedValue = settings.fields.find((f) => f.name === field.name);
1437
+ defaultValue = lastSavedValue && lastSavedValue ? lastSavedValue.value[0] : '';
1427
1438
  }
1428
- return false;
1429
- });
1439
+ // if field is find-person build a form group;
1440
+ if (field.type === 'find-person') {
1441
+ const formGroup = new FormGroup({
1442
+ domain: new FormControl(''),
1443
+ email: new FormControl(defaultValue && defaultValue.hasOwnProperty('email') ? defaultValue.email : '', validators),
1444
+ id: new FormControl(''),
1445
+ name: new FormControl(''),
1446
+ knownAs: new FormControl(''),
1447
+ });
1448
+ this.form.addControl(field.name, formGroup);
1449
+ }
1450
+ else {
1451
+ const control = new FormControl(defaultValue, validators);
1452
+ this.form.addControl(field.name, control);
1453
+ }
1454
+ // if field updates find person component set the initial domain
1455
+ if (field.findPersonField) {
1456
+ this.fieldChanged(field, this.form);
1457
+ }
1458
+ }
1430
1459
  }
1431
- return [];
1432
- }
1433
- }
1434
- UserSelectComponent.decorators = [
1435
- { type: Component, args: [{
1436
- selector: 'xuilib-user-select',
1437
- template: "<input class=\"govuk-input\" type=\"text\" [matAutocomplete]=\"dropdown\" [formControl]=\"control\" (ngModelChange)=\"onUserChange($event)\" aria-labelledby=\"add-user-hint\">\n\n<mat-autocomplete #dropdown=\"matAutocomplete\" [displayWith]=\"displayValue\" autoActiveFirstOption (optionSelected)=\"onSelected($event)\">\n <mat-option *ngFor=\"let user of filteredUsers | async\" [value]=\"user\">\n {{ user.firstName }} {{ user.lastName }} - {{ user.email }}\n </mat-option>\n</mat-autocomplete>",
1438
- styles: [""]
1439
- },] }
1440
- ];
1441
- UserSelectComponent.ctorParameters = () => [];
1442
- UserSelectComponent.propDecorators = {
1443
- users: [{ type: Input }],
1444
- selected: [{ type: Output }]
1445
- };
1446
-
1447
- class ShareCaseComponent {
1448
- constructor(stateService) {
1449
- this.stateService = stateService;
1450
- this.shareCases = []; // cases selected for sharing
1451
- this.removeUserFromCaseToggleOn = false;
1452
- this.users = []; // users of this organisation the cases can be shared with
1453
- this.confirmLink = '';
1454
- this.unselect = new EventEmitter();
1455
- this.synchronizeStore = new EventEmitter();
1456
- }
1457
- ngOnInit() {
1458
- this.shareCases$.subscribe(shareCases => {
1459
- this.shareCases = shareCases;
1460
- this.stateService.setCases(shareCases);
1461
- });
1462
- this.shareCases$ = this.stateService.state;
1463
- }
1464
- onUnselect(c) {
1465
- this.unselect.emit(c);
1466
- this.stateService.removeCase(c.caseId);
1467
- }
1468
- onSynchronizeStore(event) {
1469
- this.synchronizeStore.emit(event);
1470
1460
  }
1471
- onSelectedUser(user) {
1472
- this.selectedUser = user;
1473
- }
1474
- addUser() {
1475
- const newSharedCases = this.stateService.requestShare(this.selectedUser);
1476
- this.selectedUser = null;
1477
- if (this.userSelect) {
1478
- this.userSelect.clear();
1461
+ buildCheckBoxFormArray(field, settings) {
1462
+ const validators = GenericFilterComponent.addFormValidators(field);
1463
+ const formArray = this.fb.array([], validators);
1464
+ let defaultValues;
1465
+ if (settings && settings.fields) {
1466
+ defaultValues = settings.fields.find((f) => f.name === field.name);
1479
1467
  }
1480
- this.synchronizeStore.emit(newSharedCases);
1468
+ for (const option of field.options) {
1469
+ let checked = false;
1470
+ if (defaultValues && Array.isArray(defaultValues.value)) {
1471
+ checked = !!defaultValues.value.find((value) => value === option.key);
1472
+ }
1473
+ formArray.push(new FormControl(checked));
1474
+ }
1475
+ return formArray;
1481
1476
  }
1482
- isDisabledAdd() {
1483
- return this.selectedUser === null || this.shareCases.length === 0;
1477
+ buildFindLocationFormArray(field, settings) {
1478
+ const validators = GenericFilterComponent.addFormValidators(field);
1479
+ const formArray = this.fb.array([], validators);
1480
+ let defaultValues;
1481
+ if (settings && settings.fields) {
1482
+ defaultValues = settings.fields.find((f) => f.name === field.name);
1483
+ if (defaultValues && defaultValues.value && defaultValues.value.length > 0) {
1484
+ for (const defaultValue of defaultValues.value) {
1485
+ formArray.push(new FormControl(defaultValue));
1486
+ }
1487
+ }
1488
+ }
1489
+ return formArray;
1484
1490
  }
1485
- isDisabledContinue() {
1486
- let isDisabled = true;
1487
- this.shareCases$.subscribe(shareCases => {
1488
- for (const caseState of shareCases) {
1489
- if (caseState.pendingShares && caseState.pendingShares.length > 0) {
1490
- isDisabled = false;
1491
- break;
1491
+ getSelectedValues(formValues, config) {
1492
+ return Object.keys(formValues).map((name) => {
1493
+ const values = formValues[name];
1494
+ if (Array.isArray(values)) {
1495
+ const field = config.fields.find(f => f.name === name);
1496
+ if (field.type === 'find-location') {
1497
+ return { value: values, name };
1492
1498
  }
1493
- if (caseState.pendingUnshares && caseState.pendingUnshares.length > 0) {
1494
- isDisabled = false;
1495
- break;
1499
+ else {
1500
+ return { value: getValues(field.options, values), name };
1496
1501
  }
1497
1502
  }
1503
+ else {
1504
+ return { value: [values], name };
1505
+ }
1498
1506
  });
1499
- return isDisabled;
1500
1507
  }
1501
- onDeselect(sharedCase) {
1502
- if (sharedCase !== null) {
1503
- const updated = [];
1504
- for (const element of this.shareCases) {
1505
- if (element.caseId !== sharedCase.caseId) {
1506
- updated.push(element);
1507
- }
1508
+ emitFormErrors(form) {
1509
+ const errors = [];
1510
+ for (const field of this.config.fields) {
1511
+ const formGroup = form.get(field.name);
1512
+ if (formGroup && formGroup.errors && formGroup.errors.minLength) {
1513
+ errors.push({ name: field.name, error: field.minSelectedError });
1514
+ }
1515
+ if (formGroup && formGroup.errors && formGroup.errors.maxLength) {
1516
+ errors.push({ name: field.name, error: field.minSelectedError });
1508
1517
  }
1509
- this.shareCases = updated;
1510
1518
  }
1511
- this.stateService.setCases(this.shareCases);
1512
- }
1513
- }
1514
- ShareCaseComponent.decorators = [
1515
- { type: Component, args: [{
1516
- selector: 'xuilib-share-case',
1517
- template: "<div id=\"add-user\">\n <label class=\"govuk-label govuk-!-font-weight-bold\" for=\"add-user-input\">Enter email address</label>\n <span id=\"add-user-hint\" class=\"govuk-hint\">\n Search by name or email address. You can only add people from your organisation individually - but you can add as many as you like.\n </span>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-two-thirds\">\n <xuilib-user-select\n id=\"add-user-input\"\n aria-describedby=\"add-user-hint\"\n [users]=\"users\"\n (selected)=\"onSelectedUser($event)\">\n </xuilib-user-select>\n </div>\n <div class=\"govuk-grid-column-one-thirds\">\n <button id=\"btn-add-user\" (click)=\"addUser()\" class=\"govuk-button\" [disabled]=\"isDisabledAdd()\" title=\"Add user to the case\">Add</button>\n </div>\n </div>\n <details id=\"add-user-help\" class=\"govuk-details\" data-module=\"govuk-details\">\n <summary class=\"govuk-details__summary\">\n <span id=\"content-why-can-not-find-email\" class=\"govuk-details__summary-text\">\n Can\u2019t find an email address?\n </span>\n </summary>\n <div id=\"content-reason-can-not-find-email\" class=\"govuk-details__text\">\n If you can\u2019t find your colleague\u2019s email address, they will need to complete their registration. Contact your\n administrator for help.\n </div>\n </details>\n</div>\n\n<div id=\"cases\">\n <h3 id=\"title-selected-cases\" class=\"govuk-heading-m\">Selected cases</h3>\n <div *ngIf=\"shareCases && shareCases.length > 0\" class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"accordion-with-summary-sections\">\n <xuilib-selected-case-list\n [shareCases$]=\"shareCases$\"\n [removeUserFromCaseToggleOn]=\"removeUserFromCaseToggleOn\"\n (unselect)=\"onUnselect($event)\"\n (synchronizeStore)=\"onSynchronizeStore($event)\"\n >\n </xuilib-selected-case-list>\n </div>\n\n <div id=\"noCaseDisplay\" *ngIf=\"shareCases && shareCases.length === 0\" class=\"govuk-hint\">\n No cases to display.\n </div>\n\n</div>\n\n<div id=\"share-case-nav\">\n <button class=\"govuk-button\" [disabled]=\"isDisabledContinue()\" title=\"Continue\" [routerLink]=\"confirmLink\">Continue</button>\n</div>\n",
1518
- styles: [""]
1519
- },] }
1520
- ];
1521
- ShareCaseComponent.ctorParameters = () => [
1522
- { type: CaseSharingStateService }
1523
- ];
1524
- ShareCaseComponent.propDecorators = {
1525
- removeUserFromCaseToggleOn: [{ type: Input }],
1526
- shareCases$: [{ type: Input }],
1527
- users: [{ type: Input }],
1528
- confirmLink: [{ type: Input }],
1529
- unselect: [{ type: Output }],
1530
- synchronizeStore: [{ type: Output }],
1531
- userSelect: [{ type: ViewChild, args: [UserSelectComponent, { static: true },] }]
1532
- };
1533
-
1534
- class TabComponent {
1535
- constructor() {
1536
- this.tabChange = new EventEmitter();
1537
- }
1538
- tabChanged(event) {
1539
- this.tabChange.emit(event);
1519
+ if (errors.length) {
1520
+ this.filterService.givenErrors.next(errors);
1521
+ }
1540
1522
  }
1541
1523
  }
1542
- TabComponent.decorators = [
1524
+ GenericFilterComponent.decorators = [
1543
1525
  { type: Component, args: [{
1544
- selector: 'xuilib-tab',
1545
- template: "<mat-tab-group animationDuration=\"0ms\" (selectedTabChange)=\"tabChanged($event)\">\n <mat-tab *ngFor=\"let tabItem of tabItems; let last = last;\" [label]=\"tabItem.text\">\n </mat-tab>\n</mat-tab-group>"
1526
+ selector: 'xuilib-generic-filter',
1527
+ template: "<form [formGroup]=\"form\" (ngSubmit)=\"applyFilter(form)\">\n <div class=\"contain-classes\" *ngFor=\"let field of config.fields\">\n <hr *ngIf=\"field.lineBreakBefore\" class=\"govuk-section-break govuk-section-break--visible elevated-break\">\n <div class=\"govuk-form-group xui-generic-filter\"\n [hidden]=\"hidden(field, form)\"\n [id]=\"field.name\"\n [ngClass]=\"{'form-group-error': submitted && (form.get(field.name).errors?.minLength || form.get(field.name).errors?.maxLength)}\">\n <h3 *ngIf=\"field.title\" class=\"govuk-heading-s\">{{field.title}}</h3>\n <p class=\"govuk-body\" *ngIf=\"field.subTitle\">{{field.subTitle}}</p>\n <span [id]=\"field.name + '-error'\" class=\"govuk-error-message\" *ngIf=\"field.displayMinSelectedError && submitted && form.get(field.name).errors?.minLength\">\n <span class=\"govuk-visually-hidden\">Error:</span> {{field.minSelectedError}}\n </span>\n <span [id]=\"field.name + '-error'\" class=\"govuk-error-message\" *ngIf=\"field.displayMaxSelectedError && submitted && form.get(field.name).errors?.maxLength\">\n <span class=\"govuk-visually-hidden\">Error:</span> {{field.maxSelectedError}}\n </span>\n <div class=\"govuk-body\" [ngSwitch]=\"field.type\">\n <ng-container *ngSwitchCase=\"'select'\">\n <select class=\"govuk-select\" (change)=\"fieldChanged(field, form)\" [attr.disabled]=\"disabled(field, form)\" [name]=\"'select_' + field.name\" [id]=\"'select_' + field.name\" [formControlName]=\"field.name\">\n <option disabled selected hidden value=\"\">{{field.disabledText}}</option>\n <option class=\"govuk-radios__item\" *ngFor=\"let item of field.options\" [value]=\"item.key\">{{item.label}}</option>\n </select>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <div class=\"govuk-checkboxes govuk-checkboxes--small\" [formGroupName]=\"field.name\" [attr.field]=\"field.name\" [id]=\"'checkbox_' + field.name\">\n <div *ngFor=\"let item of field.options; let i = index\" class=\"govuk-checkboxes__item\">\n <input type=\"checkbox\" class=\"govuk-checkboxes__input\"\n [attr.disabled]=\"disabled(field, form)\"\n [formControlName]=\"i\"\n (change)=\"toggleSelectAll($event, form, item, field)\"\n [value]=\"item.key\" [id]=\"'checkbox_' + item.key\"\n [name]=\"'checkbox_' + item.key\"\n />\n <label\n [for]=\"'checkbox_' + item.key\"\n class=\"govuk-label govuk-checkboxes__label\"\n [ngClass]=\"{'govuk-!-font-weight-bold': item.selectAll}\"\n >{{item.label}}</label>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox-large'\">\n <div class=\"govuk-checkboxes\" [formGroupName]=\"field.name\" [attr.field]=\"field.name\" [id]=\"'checkbox_' + field.name\">\n <div *ngFor=\"let item of field.options; let i = index\" class=\"govuk-checkboxes__item\">\n <input type=\"checkbox\" class=\"govuk-checkboxes__input\"\n [attr.disabled]=\"disabled(field, form)\"\n [formControlName]=\"i\"\n (change)=\"toggleSelectAll($event, form, item, field)\"\n [value]=\"item.key\" [id]=\"'checkbox_' + item.key\"\n [name]=\"'checkbox_' + item.key\"\n />\n <label\n [for]=\"'checkbox_' + item.key\"\n class=\"govuk-label govuk-checkboxes__label\"\n [ngClass]=\"{'govuk-!-font-weight-bold': item.selectAll}\"\n >{{item.label}}</label>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'radio'\">\n <div class=\"govuk-radios\">\n <div *ngFor=\"let item of field.options\" class=\"govuk-radios__item\">\n <input type=\"radio\"\n [formControlName]=\"field.name\"\n [id]=\"'radio_' + item.key\"\n [attr.disabled]=\"disabled(field, form)\"\n [checked]=\"item.key === form.get(field.name).value\"\n class=\"govuk-radios__input\"\n [value]=\"item.key\"\n (change)=\"fieldChanged(field, form)\"\n />\n <label [for]=\"'radio_' + item.key\" class=\"govuk-label govuk-radios__label\">{{item.label}}</label>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'find-person'\">\n <xuilib-find-person subTitle=\"\" (personSelected)=\"updatePersonControls($event, field)\"\n (personFieldChanged)=\"inputChanged(field)\"\n [submitted]=\"submitted\"\n [disabled]=\"disabled(field, form)\"\n [domain]=\"form.get(field.domainField)?.value\"\n [findPersonGroup]=\"form\"\n [selectedPerson]=\"form.get(field.name)?.value?.email\"\n [userIncluded]=\"false\"\n ></xuilib-find-person>\n </ng-container>\n <ng-container *ngSwitchCase=\"'find-location'\">\n <xuilib-find-location (locationFieldChanged)=\"inputChanged(field)\"\n [form]=\"form\"\n [fields]=\"config.fields\"\n [locationTitle]=\"field.locationTitle\"\n [enableAddLocationButton]=\"field.enableAddLocationButton\"\n [disabled]=\"disabled(field, form)\"\n [disableInputField]=\"field.disable\"\n [selectedLocations]=\"form.get(field.name)?.value\"\n [submitted]=\"submitted\"\n [services]=\"form.get(field.findLocationField)?.value\"\n [field]=\"field\"\n ></xuilib-find-location>\n </ng-container>\n </div>\n </div>\n </div>\n <hr class=\"govuk-section-break govuk-section-break--m govuk-section-break--visible\"/>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-full\">\n <button\n class=\"govuk-button govuk-!-margin-right-1 govuk-!-margin-bottom-0\"\n type=\"submit\"\n id=\"applyFilter\"\n [disabled]=\"config.enableDisabledButton && form.invalid\"\n >{{config.applyButtonText || 'Apply'}}</button>\n <button *ngIf=\"config.showCancelFilterButton\"\n class=\"govuk-button govuk-button--secondary govuk-!-margin-bottom-0\"\n type=\"button\"\n id=\"cancelFilter\"\n (click)=\"cancelFilter()\">{{ config.cancelButtonText || 'Cancel'}}</button>\n </div>\n </div>\n</form>\n",
1528
+ changeDetection: ChangeDetectionStrategy.OnPush,
1529
+ encapsulation: ViewEncapsulation.None,
1530
+ styles: [".contain-classes .elevated-break{position:relative;top:-10px}.contain-classes .xui-generic-filter .select-all{margin-bottom:10px}.contain-classes .xui-generic-filter .govuk-checkboxes{display:flex;flex-wrap:wrap}.contain-classes .xui-generic-filter .govuk-checkboxes>div{flex-grow:1;flex-shrink:0}"]
1546
1531
  },] }
1547
1532
  ];
1548
- TabComponent.ctorParameters = () => [];
1549
- TabComponent.propDecorators = {
1550
- tabItems: [{ type: Input }],
1551
- tabChange: [{ type: Output }]
1552
- };
1553
-
1554
- class TcConfirmComponent {
1555
- constructor() {
1556
- this.confirm = new EventEmitter();
1557
- }
1558
- onClick() {
1559
- this.confirm.emit();
1560
- }
1561
- }
1562
- TcConfirmComponent.decorators = [
1563
- { type: Component, args: [{
1564
- selector: 'xuilib-tc-confirm',
1565
- template: "<div class=\"govuk-width-container\">\n <main role=\"main\" class=\"govuk-main-wrapper\">\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-two-thirds\">\n <div class=\"column-two-thirds\">\n <h1 class=\"govuk-heading-xl\">Using this service</h1>\n <h2 class=\"govuk-heading-m\">Terms and conditions</h2>\n <p>We've recently updated the\n <a\n routerLink=\"/terms-and-conditions\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >terms and conditions</a\n >.\n </p>\n <p>You must review and accept them.\n </p>\n <p>\n <button class=\"govuk-button\" (click)=\"onClick()\">\n {{ buttonText }}\n </button>\n </p>\n </div>\n </div>\n </div>\n <div class=\"govuk-grid-column-one-third\"></div>\n </main>\n</div>\n",
1566
- styles: [""]
1567
- },] }
1533
+ GenericFilterComponent.ctorParameters = () => [
1534
+ { type: FilterService },
1535
+ { type: FormBuilder }
1568
1536
  ];
1569
- TcConfirmComponent.ctorParameters = () => [];
1570
- TcConfirmComponent.propDecorators = {
1571
- buttonText: [{ type: Input }],
1572
- confirm: [{ type: Output }]
1537
+ GenericFilterComponent.propDecorators = {
1538
+ config: [{ type: Input }],
1539
+ settings: [{ type: Input }]
1573
1540
  };
1574
1541
 
1575
- class TcDisplayHtmlComponent {
1576
- constructor() { }
1542
+ /*
1543
+ * Gov UK Dialog Component
1544
+ * Responsible for displaying dialog layout
1545
+ * using ng-content to display content from parent
1546
+ * */
1547
+ class HmctsSessionDialogComponent {
1548
+ constructor() {
1549
+ this.close = new EventEmitter();
1550
+ }
1551
+ onClose() {
1552
+ this.close.emit();
1553
+ }
1577
1554
  }
1578
- TcDisplayHtmlComponent.decorators = [
1555
+ HmctsSessionDialogComponent.decorators = [
1579
1556
  { type: Component, args: [{
1580
- selector: 'xuilib-tc-display-html',
1581
- template: "<ng-content></ng-content>",
1582
- styles: [":host{display:block;width:100%}"]
1557
+ selector: 'xuilib-session-dialog',
1558
+ template: "<div class=\"gem-c-modal-dialogue\" data-module=\"modal-dialogue\" id=\"modal-default\" style=\"display: block;\">\n <div class=\"gem-c-modal-dialogue__overlay\"></div>\n <dialog class=\"gem-c-modal-dialogue__box\" aria-modal=\"true\" role=\"dialog\" tabindex=\"0\" [ngStyle]=\"{'margin-top': positionTop}\">\n <div class=\"gem-c-modal-dialogue__header\">\n <svg role=\"presentation\" focusable=\"false\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 38 38\" height=\"33\" width=\"33\">\n <style type=\"text/css\">\n .st0{fill:#FFFFFF;}\n </style>\n <g id=\"_4_-_granular_components_warning_icon\" transform=\"translate(0.5 0.5)\">\n <g id=\"Warning_icon\" transform=\"translate(0)\">\n <path id=\"Exclusion_1\" class=\"st0\" d=\"M18.5,37.5c-5.04,0.01-9.88-1.99-13.44-5.57C1.49,28.38-0.51,23.54-0.5,18.5\n c-0.01-5.04,1.99-9.88,5.56-13.43C8.62,1.49,13.46-0.51,18.5-0.5c5.04-0.01,9.88,1.99,13.44,5.56c3.57,3.56,5.58,8.39,5.56,13.44\n c0.01,5.04-1.99,9.88-5.56,13.44C28.38,35.51,23.54,37.51,18.5,37.5z M18.52,24.29c-0.4,0-0.8,0.08-1.17,0.23\n c-0.36,0.15-0.69,0.37-0.97,0.64c-0.28,0.27-0.5,0.59-0.65,0.95c-0.16,0.36-0.24,0.76-0.23,1.15c0,0.4,0.08,0.8,0.23,1.17\n c0.15,0.36,0.37,0.68,0.65,0.96c0.28,0.27,0.61,0.49,0.97,0.64c0.37,0.16,0.77,0.24,1.17,0.24c0.4,0,0.79-0.08,1.15-0.24\n c0.35-0.15,0.67-0.37,0.95-0.64c0.27-0.27,0.49-0.6,0.64-0.96c0.16-0.37,0.24-0.77,0.23-1.17c0-0.4-0.08-0.79-0.23-1.15\n c-0.15-0.35-0.37-0.67-0.64-0.95c-0.27-0.27-0.6-0.49-0.95-0.64C19.31,24.37,18.92,24.29,18.52,24.29L18.52,24.29z M16.11,7.5\n l0.42,14.87h3.91L20.86,7.5H16.11z\"/>\n </g>\n </g>\n </svg>\n <div class=\"gem-c-modal-dialogue__title\">We are about to sign you out</div>\n </div>\n <div class=\"gem-c-modal-dialogue__content\">\n <ng-content></ng-content>\n </div>\n </dialog>\n</div>\n",
1559
+ styles: [".gem-c-modal-dialogue{display:none;z-index:1000;overflow-x:hidden;overflow-y:scroll;outline:0}.gem-c-modal-dialogue,.gem-c-modal-dialogue__box{position:fixed;top:0;left:0;width:100%;height:100%}.gem-c-modal-dialogue__box{display:block;background:#fff;right:0;bottom:0;margin:0;padding:0;overflow-y:auto;border:0;font-family:GDS Transport,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-size:16px;font-size:1rem;line-height:1.25;color:#0b0c0c}.gem-c-modal-dialogue__box:focus{outline:3px solid #fd0}@media print{.gem-c-modal-dialogue__box{font-family:sans-serif}}@media (min-width:40.0625em){.gem-c-modal-dialogue__box{font-size:1.1875rem;line-height:1.3157894737}}@media print{.gem-c-modal-dialogue__box{font-size:14pt;line-height:1.15;color:#000}}@media (min-width:40.0625em){.gem-c-modal-dialogue__box{position:relative;top:inherit;right:inherit;bottom:inherit;left:inherit;width:auto;max-width:640px;height:auto;margin:30px auto;border:2px solid #0b0c0c}}@media (min-width:40.0625em){.gem-c-modal-dialogue__box--wide{max-width:960px}}@media (min-width:40.0625em) and (max-width:64em){.gem-c-modal-dialogue__box--wide{margin:30px}}.gem-c-modal-dialogue__overlay{position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;opacity:.8;background:#0b0c0c;pointer-events:none;touch-action:none}@media screen{.gem-o-template--modal{overflow-y:inherit}}.gem-o-template__body--modal{overflow:hidden}.gem-o-template__body--blur .govuk-footer,.gem-o-template__body--blur .govuk-header,.gem-o-template__body--blur .govuk-main-wrapper,.gem-o-template__body--blur .govuk-phase-banner,.gem-o-template__body--blur .govuk-skip-link,.gem-o-template__body--blur .govuk-width-container .govuk-back-link{filter:blur(2px)}.govuk-warning-text__icon{margin:0 0 0 12px}.gem-c-modal-dialogue__header{padding:9px 15px 10px;color:#fff;background:#d4351d;display:flex}.gem-c-modal-dialogue__title{margin:5px 0 4px 12px}.gem-c-modal-dialogue__logotype-crown{fill:currentColor;vertical-align:middle}.gem-c-modal-dialogue__logotype-crown-fallback-image{width:30px;height:26px;border:0;vertical-align:middle}.gem-c-modal-dialogue__content{padding:15px;background:#fff}.gem-c-modal-dialogue__close-button{position:absolute;top:0;right:0;width:44px;height:44px;border:0;color:#fff;background:none;cursor:pointer;font-family:GDS Transport,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:700;font-size:1.5rem;line-height:1.3}@media print{.gem-c-modal-dialogue__close-button{font-family:sans-serif}}@media (min-width:40.0625em){.gem-c-modal-dialogue__close-button{font-size:2.25rem;line-height:1.3}}@media print{.gem-c-modal-dialogue__close-button{font-size:24pt;line-height:1.3}}@media (max-width:40.0525em){.gem-c-modal-dialogue__close-button{font-size:36px;line-height:1.3}}.gem-c-modal-dialogue__close-button:focus,.gem-c-modal-dialogue__close-button:hover{color:#0b0c0c;box-shadow:0 -2px #fd0,0 4px #0b0c0c;text-decoration:none;outline:none;background:#fd0}"]
1583
1560
  },] }
1584
1561
  ];
1585
- TcDisplayHtmlComponent.ctorParameters = () => [];
1562
+ HmctsSessionDialogComponent.ctorParameters = () => [];
1563
+ HmctsSessionDialogComponent.propDecorators = {
1564
+ positionTop: [{ type: Input }],
1565
+ close: [{ type: Output }]
1566
+ };
1586
1567
 
1587
- class TcDisplayPlainComponent {
1588
- constructor() { }
1568
+ class InviteUserFormComponent {
1569
+ constructor() {
1570
+ this.submitForm = new EventEmitter();
1571
+ }
1572
+ set errorMessages(value) {
1573
+ this.isInvalid = value || {};
1574
+ }
1575
+ onSubmit() {
1576
+ this.submitForm.emit();
1577
+ }
1589
1578
  }
1590
- TcDisplayPlainComponent.decorators = [
1579
+ InviteUserFormComponent.decorators = [
1591
1580
  { type: Component, args: [{
1592
- selector: 'xuilib-tc-display-plain',
1593
- template: "<ng-content></ng-content>",
1594
- styles: [":host{display:block;width:100%}"]
1581
+ selector: 'xuilib-invite-user-form',
1582
+ template: "\n<form [formGroup]=\"inviteUserForm\" (ngSubmit)=\"onSubmit()\" >\n\n <xuilib-gov-uk-input\n [config]=\"{label: 'First name', hint: 'Include all middle names.', name: 'firstName', id: 'firstName', type: 'text', classes: 'testClass'}\"\n [errorMessage]=\"isInvalid.firstName\"\n [group]=\"inviteUserForm\">\n </xuilib-gov-uk-input>\n\n <xuilib-gov-uk-input\n [config]=\"{label: 'Last name', name: 'lastName', id: 'lastName', type: 'text'}\"\n [errorMessage]=\"isInvalid.lastName\"\n [group]=\"inviteUserForm\">\n </xuilib-gov-uk-input>\n\n <xuilib-gov-uk-input\n [config]=\"{label: 'Email address', name: 'email', id: 'email', type: 'email'}\"\n [errorMessage]=\"isInvalid.email\"\n [group]=\"inviteUserForm\">\n </xuilib-gov-uk-input>\n\n <xuilib-invite-permission-form [inviteUserForm]=\"inviteUserForm\" [errorMessages]=\"isInvalid.roles\">\n </xuilib-invite-permission-form>\n\n <button type=\"submit\" class=\"govuk-button\">\n Send invitation\n </button>\n</form>\n"
1595
1583
  },] }
1596
1584
  ];
1597
- TcDisplayPlainComponent.ctorParameters = () => [];
1585
+ InviteUserFormComponent.propDecorators = {
1586
+ submitForm: [{ type: Output }],
1587
+ inviteUserForm: [{ type: Input }],
1588
+ errorMessages: [{ type: Input }]
1589
+ };
1598
1590
 
1599
- class TermsAndConditionsComponent {
1600
- constructor() { }
1591
+ class InviteUserPermissionComponent {
1592
+ constructor() {
1593
+ this.isPuiCaseManager = false;
1594
+ this.isPuiUserManager = false;
1595
+ this.isPuiOrganisationManager = false;
1596
+ this.isPuiFinanceManager = false;
1597
+ }
1601
1598
  }
1602
- TermsAndConditionsComponent.decorators = [
1599
+ InviteUserPermissionComponent.decorators = [
1603
1600
  { type: Component, args: [{
1604
- selector: 'xuilib-terms-and-conditions',
1605
- template: "<ng-container [ngSwitch]=\"document.mimeType\">\n <xuilib-tc-display-html *ngSwitchCase=\"'text/html'\">\n <div [innerHTML]=\"document.content\"></div>\n </xuilib-tc-display-html>\n <xuilib-tc-display-plain *ngSwitchCase=\"'text/plain'\">\n {{ document.content }}\n </xuilib-tc-display-plain>\n <div *ngSwitchDefault>\n An error occured. Please try again.\n </div>\n</ng-container>\n",
1606
- styles: [":host{display:block;width:100%}"]
1601
+ selector: 'xuilib-invite-permission-form',
1602
+ template: " <!--permissions -->\n <ng-container [formGroup]=\"inviteUserForm\">\n <xuilib-gov-uk-form-group-wrapper\n [config]=\"{hint: 'Choose what the user will be able to do. You can change this later.', legend: 'Permissions', key: 'roles'}\"\n [formGroupName]=\"'roles'\"\n [error]=\"errorMessages\">\n\n <div class=\"govuk-checkboxes\">\n <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiCaseManager\"\n [config]=\"{value: 'pui-case-manager', label: 'Manage Cases', name: 'roles', hint: 'View, create and progress cases.', focusOn: 'roles'}\">\n </xuilib-gov-checkbox>\n\n <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiUserManager\"\n [config]=\"{value: 'pui-user-manager', label: 'Manage Users', name: 'roles',\n hint: 'Invite users.'}\">\n </xuilib-gov-checkbox>\n\n <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiOrganisationManager\"\n [config]=\"{value: 'pui-organisation-manager', label: 'Manage Organisation', name: 'roles',\n hint: 'View organisation name and addresses.'}\">\n </xuilib-gov-checkbox>\n\n <!-- <xuilib-gov-checkbox\n [group]=\"inviteUserForm.controls['roles']\"\n [isChecked]=\"isPuiFinanceManager\"\n [config]=\"{value: 'pui-finance-manager', label: 'Manage Payments', name: 'roles',\n hint: 'View account balances, available credit and transactions.'}\">\n </xuilib-gov-checkbox> -->\n </div>\n\n </xuilib-gov-uk-form-group-wrapper>\n</ng-container>"
1607
1603
  },] }
1608
1604
  ];
1609
- TermsAndConditionsComponent.ctorParameters = () => [];
1610
- TermsAndConditionsComponent.propDecorators = {
1611
- document: [{ type: Input }]
1605
+ InviteUserPermissionComponent.propDecorators = {
1606
+ inviteUserForm: [{ type: Input }],
1607
+ isPuiCaseManager: [{ type: Input }],
1608
+ isPuiUserManager: [{ type: Input }],
1609
+ isPuiOrganisationManager: [{ type: Input }],
1610
+ isPuiFinanceManager: [{ type: Input }],
1611
+ errorMessages: [{ type: Input }]
1612
1612
  };
1613
1613
 
1614
- class UserDetailsComponent {
1614
+ class LoadingSpinnerComponent {
1615
1615
  constructor() {
1616
- this.showEditLink = false;
1617
- this.showHelpLink = false;
1618
- this.suspendUserEvent = new EventEmitter();
1619
- this.showSuspendUserButton = false;
1620
- this.reinvite = new EventEmitter();
1621
- }
1622
- reinviteClick(user) {
1623
- this.reinvite.emit(user);
1624
- }
1625
- suspendUser(suspendUser) {
1626
- this.suspendUserEvent.emit(suspendUser);
1627
- }
1628
- userHasRole(theRole) {
1629
- if (this.user && this.user.roles) {
1630
- return this.user.roles.includes(theRole);
1631
- }
1632
- return false;
1616
+ this.loadingText = 'Loading';
1633
1617
  }
1634
1618
  }
1635
- UserDetailsComponent.decorators = [
1619
+ LoadingSpinnerComponent.decorators = [
1636
1620
  { type: Component, args: [{
1637
- selector: 'xuilib-user-details',
1638
- template: "<div class=\"govuk-warning-text\" *ngIf=\"warningTitle && warningTitle !== ''\">\n<span class=\"govuk-warning-text__icon\">!</span>\n<strong class=\"govuk-warning-text__text\">\n {{ warningTitle }}\n</strong>\n</div>\n<table class=\"govuk-table\" *ngIf=\"user\">\n <tbody class=\"govuk-table__body\">\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header\" scope=\"row\">Name</th>\n <td class=\"govuk-table__cell\">{{user.fullName}}</td>\n <td class=\"govuk-table__cell\"></td>\n </tr>\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header\" scope=\"row\">Email address</th>\n <td class=\"govuk-table__cell\">{{user.email}}</td>\n <td class=\"govuk-table__cell\"></td>\n </tr>\n <tr class=\"govuk-table__row\" *ngIf=\"!user.resendInvite\">\n <th class=\"govuk-table__header\" scope=\"row\">Permissions</th>\n <td class=\"govuk-table__cell\">\n <div *ngIf=\"user.manageOrganisations === 'Yes'\">Manage organisations</div>\n <div *ngIf=\"user.manageUsers === 'Yes'\">Manage users</div>\n <div *ngIf=\"user.manageCases === 'Yes'\">Manage cases</div>\n <div *ngIf=\"userHasRole('pui-caa')\">Case access administrator</div>\n <div *ngIf=\"userHasRole('pui-finance-manager')\">Manage fee accounts</div>\n </td>\n <td class=\"govuk-table__cell\"><a *ngIf=\"editPermissionRouterLink && showEditLink\" [routerLink]=\"editPermissionRouterLink\">Change <span class=\"govuk-visually-hidden\">roles</span></a></td>\n </tr>\n </tbody>\n</table>\n<button *ngIf=\"showSuspendUserButton\" class=\"govuk-button govuk-button--warning\" (click)=\"suspendUser(user)\">\n Suspend account\n</button>\n<div *ngIf=\"user && user.resendInvite\">\n <div class=\"govuk-inset-text\">\n <p>This user has already been invited but has not activated their account.</p>\n <p>If you resend an invitation, they'll receive an email from HM Courts and Tribunals to finish setting up their account.</p>\n <p>You can't invite the same user more than once an hour.</p>\n </div>\n <a role=\"button\" draggable=\"false\" class=\"govuk-button\" (click)=\"reinviteClick(user)\" id=\"resend-invite-button\">\n Resend invitation\n </a>\n</div>\n<p class=\"govuk-body\" *ngIf=\"showHelpLink && suspendHelpLink\"><a [routerLink]=\"suspendHelpLink\" target=\"_blank\">Get help</a> to reactivate this account.</p>\n",
1639
- styles: [":host{display:block}"]
1621
+ selector: 'xuilib-loading-spinner',
1622
+ template: "<div class=\"spinner-container\">\n <div class=\"spinner-inner-container\">\n <p>{{loadingText}}</p>\n <div class=\"spinner\" style=\"margin: auto;\"></div>\n </div>\n</div>\n",
1623
+ encapsulation: ViewEncapsulation.None,
1624
+ styles: [".spinner-container{position:fixed;top:0;left:0;height:100%;width:100%;display:flex;justify-content:center;align-items:center;background:hsla(0,0%,100%,.5);z-index:99}.spinner-container .spinner-inner-container p{text-align:center}.spinner-container .spinner-inner-container .spinner{border:10px solid #ddd;border-top-color:#000;border-radius:50%;width:40px;height:40px;-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}"]
1640
1625
  },] }
1641
1626
  ];
1642
- UserDetailsComponent.propDecorators = {
1643
- user: [{ type: Input }],
1644
- editPermissionRouterLink: [{ type: Input }],
1645
- warningTitle: [{ type: Input }],
1646
- showEditLink: [{ type: Input }],
1647
- showHelpLink: [{ type: Input }],
1648
- suspendHelpLink: [{ type: Input }],
1649
- suspendUserEvent: [{ type: Output }],
1650
- showSuspendUserButton: [{ type: Input }],
1651
- reinvite: [{ type: Output }]
1627
+ LoadingSpinnerComponent.propDecorators = {
1628
+ loadingText: [{ type: Input }]
1652
1629
  };
1653
1630
 
1654
- class UserListComponent {
1631
+ class PaginationComponent {
1655
1632
  constructor() {
1656
- this.users = [];
1657
- this.userClick = new EventEmitter();
1658
- this.pageChange = new EventEmitter();
1659
- }
1660
- ngOnInit() {
1661
- this.pagination = { itemsPerPage: 50, currentPage: this.currentPageNumber, totalItems: this.pageTotalSize };
1633
+ this.previousPage = new EventEmitter();
1634
+ this.nextPage = new EventEmitter();
1662
1635
  }
1663
- onUserClick(user) {
1664
- this.userClick.emit(user);
1636
+ onPrevious() {
1637
+ this.previousPage.emit(null);
1665
1638
  }
1666
- emitPageClickEvent(pageNumber) {
1667
- this.currentPageNumber = pageNumber;
1668
- this.pageChange.emit(pageNumber);
1639
+ onNext() {
1640
+ this.nextPage.emit(null);
1669
1641
  }
1670
1642
  }
1671
- UserListComponent.decorators = [
1643
+ PaginationComponent.decorators = [
1672
1644
  { type: Component, args: [{
1673
- selector: 'xuilib-user-list',
1674
- template: "<table class=\"govuk-table\">\n\n <thead clas=\"govuk-table__head\">\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header\" scope=\"col\">Name</th>\n <th class=\"govuk-table__header\" scope=\"col\">Email</th>\n <th class=\"govuk-table__header\" scope=\"col\">Status</th>\n </tr>\n </thead>\n <tbody class=\"govuk-table__body\">\n <ng-container *ngFor=\"let u of users | paginate: { itemsPerPage: pagination.itemsPerPage, currentPage: currentPageNumber, totalItems: pagination.totalItems }\">\n <tr class=\"govuk-table__row\" data-selector=\"table-row\">\n <td class=\"govuk-table__cell\" data-selector=\"table-cell\">\n <a class=\"govuk-link\" [attr.title]=\"u.routerLinkTitle\" [routerLink]=\"u.routerLink\" (click)=\"onUserClick(u)\">{{ u.fullName }}</a>\n </td>\n <td class=\"govuk-table__cell\" data-selector=\"table-cell\">{{ u.email }}</td>\n <td class=\"govuk-table__cell\" data-selector=\"table-cell\">{{ u.status }}</td>\n </tr>\n </ng-container>\n </tbody>\n</table>\n<xuilib-hmcts-pagination (pageChange)=\"emitPageClickEvent($event)\" [pageSize]=\"pagination.itemsPerPage\"></xuilib-hmcts-pagination>\n",
1675
- styles: [":host{display:block}"]
1645
+ selector: 'xuilib-pagination',
1646
+ template: "<nav class=\"hmcts-pagination\" id=\"pagination-label\">\n\n <p class=\"govuk-visually-hidden\" aria-labelledby=\"pagination-label\">Pagination navigation</p>\n\n <ul class=\"hmcts-pagination__list\">\n <li class=\"hmcts-pagination__item hmcts-pagination__item--prev\">\n <a *ngIf=\"firstRecord > 1; else noPrevious\" class=\"hmcts-pagination__link\" (click)=\"onPrevious()\" href=\"javascript:void(0)\">\n Previous page\n </a>\n <ng-template #noPrevious>\n <span class=\"hmcts-pagination__link\">Previous page</span>\n </ng-template>\n </li>\n\n <li class=\"hmcts-pagination__item hmcts-pagination__item--next\">\n <a *ngIf=\"moreItems; else noNext\" class=\"hmcts-pagination__link\" (click)=\"onNext()\" href=\"javascript:void(0)\">Next page</a>\n <ng-template #noNext>\n <span class=\"hmcts-pagination__link\">Next page</span>\n </ng-template>\n </li>\n </ul>\n</nav>\n",
1647
+ styles: ["span.hmcts-pagination__link:hover{color:revert}"]
1676
1648
  },] }
1677
1649
  ];
1678
- UserListComponent.propDecorators = {
1679
- users: [{ type: Input }],
1680
- currentPageNumber: [{ type: Input }],
1681
- pageTotalSize: [{ type: Input }],
1682
- userClick: [{ type: Output }],
1683
- pageChange: [{ type: Output }]
1650
+ PaginationComponent.ctorParameters = () => [];
1651
+ PaginationComponent.propDecorators = {
1652
+ moreItems: [{ type: Input }],
1653
+ firstRecord: [{ type: Input }],
1654
+ previousPage: [{ type: Output }],
1655
+ nextPage: [{ type: Output }]
1684
1656
  };
1685
1657
 
1686
- class CookieService {
1687
- constructor(doc) {
1688
- this.document = doc;
1689
- }
1690
- setCookie(key, value, expiryDate) {
1691
- const expiry = expiryDate ? ` expires=${expiryDate}` : '';
1692
- const cookie = `${key}=${value};${expiry}`;
1693
- this.document.cookie = cookie;
1694
- }
1695
- getCookie(key) {
1696
- const cookieValue = this.document.cookie
1697
- .split('; ')
1698
- .find(row => row.startsWith(`${key}=`))
1699
- .split('=')[1];
1700
- return cookieValue;
1658
+ class SearchJudicialsComponent {
1659
+ constructor(judicialService, fb) {
1660
+ this.judicialService = judicialService;
1661
+ this.disabled = null;
1662
+ this.selectedJudicials = [];
1663
+ this.submitted = true;
1664
+ this.placeholderContent = '';
1665
+ this.showAutocomplete = false;
1666
+ this.judicialChanged = new EventEmitter();
1667
+ this.idValue = '';
1668
+ this.errorMessage = 'You must select a name';
1669
+ this.serviceId = '';
1670
+ this.minSearchCharacters = 3;
1671
+ this.keyUpSubject$ = new Subject();
1672
+ this.searchInProgress = false;
1673
+ this.formGroup = fb.group({
1674
+ formControl: [null],
1675
+ selectedFormControl: [null]
1676
+ });
1701
1677
  }
1702
- deleteCookie(key, path, domain) {
1703
- const pathValue = path ? `; path=${path}` : '';
1704
- const domainValue = domain ? `; domain=${domain}` : '';
1705
- this.document.cookie = `${key}=${pathValue}${domainValue}; expires=Thu, 01 Jan 1970 00:00:01 GMT; max-age=0`;
1678
+ ngOnInit() {
1679
+ this.displayedJudicials = [];
1680
+ if (this.control) {
1681
+ if (this.formGroup && this.formGroup.controls) {
1682
+ this.formGroup.controls.selectedFormControl = this.control;
1683
+ this.formGroup.controls.formControl.setValue(this.getControlValueDisplayText());
1684
+ }
1685
+ }
1686
+ this.keyUpSubject$.pipe(debounceTime(500)).subscribe(searchValue => this.search(searchValue));
1706
1687
  }
1707
- deleteCookieByPartialMatch(key, path, domain) {
1708
- this.document.cookie
1709
- .split('; ')
1710
- .filter(row => row.startsWith(`${key}`))
1711
- .forEach(element => {
1712
- this.deleteCookie(element.split('=')[0], path, domain);
1713
- });
1688
+ onKeyDown() {
1689
+ this.judicialChanged.emit();
1714
1690
  }
1715
- checkCookie(key) {
1716
- return this.document.cookie.split('; ').some(item => item.trim().startsWith(`${key}=`));
1691
+ onKeyUp(event) {
1692
+ this.showAutocomplete = false;
1693
+ this.keyUpSubject$.next(event.target.value);
1717
1694
  }
1718
- }
1719
- CookieService.ɵprov = i0.ɵɵdefineInjectable({ factory: function CookieService_Factory() { return new CookieService(i0.ɵɵinject(i4.DOCUMENT)); }, token: CookieService, providedIn: "root" });
1720
- CookieService.decorators = [
1721
- { type: Injectable, args: [{
1722
- providedIn: 'root'
1723
- },] }
1724
- ];
1725
- CookieService.ctorParameters = () => [
1726
- { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
1727
- ];
1728
-
1729
- const windowToken = new InjectionToken('Window');
1730
- function windowProvider() { return window; }
1731
-
1732
- class CookieBannerComponent {
1733
- constructor(cookieService, window) {
1734
- this.cookieService = cookieService;
1735
- this.rejectionNotifier = new EventEmitter();
1736
- this.acceptanceNotifier = new EventEmitter();
1737
- this.isCookieBannerVisible = false;
1738
- this.window = window;
1695
+ onFocus() {
1696
+ this.showAutocomplete = false;
1739
1697
  }
1740
- ngOnInit() {
1741
- this.setState();
1698
+ get displayedJudicialsDuplicationFiltered() {
1699
+ return this.displayedJudicials.filter(judicial => !this.selectedJudicials.map(selectedJudicial => selectedJudicial.idamId).includes(judicial.idamId));
1742
1700
  }
1743
- acceptCookie() {
1744
- this.cookieService.setCookie(this.identifier, 'true', this.getExpiryDate());
1745
- this.setState(true);
1701
+ filter(term) {
1702
+ this.searchJudicials(term, this.serviceId).pipe(mergeMap((apiData) => {
1703
+ const apiFilter = apiData.filter(apiJudicial => !this.selectedJudicials.map(selectedJudicial => selectedJudicial.idamId).includes(apiJudicial.idamId));
1704
+ this.displayedJudicials = apiFilter;
1705
+ this.searchInProgress = false;
1706
+ return apiFilter;
1707
+ })).subscribe(judicial => {
1708
+ if (term === judicial.knownAs) {
1709
+ this.formGroup.controls.selectedFormControl.setValue(judicial);
1710
+ this.displayedJudicials = [];
1711
+ this.judicialChanged.emit(judicial);
1712
+ this.showAutocomplete = false;
1713
+ }
1714
+ this.searchInProgress = false;
1715
+ });
1746
1716
  }
1747
- rejectCookie() {
1748
- this.cookieService.setCookie(this.identifier, 'false', this.getExpiryDate());
1749
- this.setState(true);
1717
+ onSelectionChange(selection) {
1718
+ if (this.formGroup.controls.formControl instanceof FormArray) {
1719
+ this.formGroup.controls.selectedFormControl.push(new FormControl(selection.idamId));
1720
+ }
1721
+ else {
1722
+ this.formGroup.controls.selectedFormControl.setValue(selection);
1723
+ }
1724
+ this.judicialChanged.emit(selection);
1750
1725
  }
1751
- setState(reload = false) {
1752
- this.isCookieBannerVisible = !this.cookieService.checkCookie(this.identifier);
1753
- if (this.areCookiesAccepted()) {
1754
- this.notifyAcceptance();
1726
+ search(currentValue) {
1727
+ this.searchInProgress = true;
1728
+ this.showAutocomplete = !!currentValue && (currentValue.length >= this.minSearchCharacters);
1729
+ if (!!currentValue) {
1730
+ this.formGroup.controls.selectedFormControl.markAsDirty();
1755
1731
  }
1756
1732
  else {
1757
- this.notifyRejection();
1733
+ this.formGroup.controls.selectedFormControl.reset();
1758
1734
  }
1759
- if (reload) { // reload if any of the buttons are pressed
1760
- this.window.location.reload();
1735
+ if (this.showAutocomplete) {
1736
+ this.filter(currentValue);
1737
+ }
1738
+ else {
1739
+ this.searchInProgress = false;
1761
1740
  }
1762
1741
  }
1763
- areCookiesAccepted() {
1764
- return this.cookieService.checkCookie(this.identifier) && this.cookieService.getCookie(this.identifier) === 'true';
1765
- }
1766
- notifyRejection() {
1767
- this.rejectionNotifier.emit();
1742
+ getDisplayName(selectedJudicial) {
1743
+ return `${selectedJudicial.knownAs} (${selectedJudicial.emailId})`;
1768
1744
  }
1769
- notifyAcceptance() {
1770
- this.acceptanceNotifier.emit();
1745
+ searchJudicials(term, serviceId) {
1746
+ return this.judicialService.searchJudicial(term, serviceId);
1771
1747
  }
1772
- getExpiryDate() {
1773
- const now = new Date();
1774
- const time = now.getTime();
1775
- const expireTime = time + 31536000000; // in 365 days = 3600 * 1000 * 24 * 365
1776
- now.setTime(expireTime);
1777
- return now.toUTCString();
1748
+ getControlValueDisplayText() {
1749
+ return this.formGroup && this.formGroup.controls && this.formGroup.controls.selectedFormControl.value ?
1750
+ this.getDisplayName(this.formGroup.controls.selectedFormControl.value) : '';
1778
1751
  }
1779
1752
  }
1780
- CookieBannerComponent.decorators = [
1753
+ SearchJudicialsComponent.decorators = [
1781
1754
  { type: Component, args: [{
1782
- selector: 'xuilib-cookie-banner',
1783
- template: "<div class=\"govuk-cookie-banner \" role=\"region\" attr.aria-label=\"'Cookies on {{appName}}'\" *ngIf=\"isCookieBannerVisible\">\n <div class=\"govuk-cookie-banner__message govuk-width-container\">\n\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-two-thirds\">\n <h2 class=\"govuk-cookie-banner__heading govuk-heading-m\">Cookies on {{appName}}</h2>\n\n <div class=\"govuk-cookie-banner__content\">\n <p>We use some essential cookies to make this service work.</p>\n <p>We\u2019d also like to use analytics cookies so we can understand how you use the service and make improvements.</p>\n </div>\n </div>\n </div>\n\n <div class=\"govuk-button-group\">\n <button value=\"accept\" type=\"button\" name=\"cookies\" class=\"govuk-button\" data-module=\"govuk-button\" (click)=\"acceptCookie()\">\n Accept analytics cookies\n </button>\n <button value=\"reject\" type=\"button\" name=\"cookies\" class=\"govuk-button\" data-module=\"govuk-button\" (click)=\"rejectCookie()\">\n Reject analytics cookies\n </button>\n <a class=\"govuk-link\" routerLink=\"/cookies\">View cookies</a>\n </div>\n </div>\n</div>"
1755
+ selector: 'xuilib-search-judicials',
1756
+ template: "<div class=\"govuk-form-group\">\n <input id=\"inputSelectPerson{{idValue}}\" [placeholder]=\"placeholderContent\" [formControl]=\"formGroup.controls.formControl\"\n [matAutocomplete]=\"autoComplete\" (keydown)=\"onKeyDown()\" (keyup)=\"onKeyUp($event)\" (focus)=\"onFocus()\"\n class=\"govuk-input\" [attr.disabled]=\"!disabled ? null: disabled\" [value]=\"getControlValueDisplayText()\"\n #inputSelection>\n <mat-autocomplete autoActiveFirstOption #autoComplete=\"matAutocomplete\">\n <mat-option *ngFor=\"let judicial of displayedJudicialsDuplicationFiltered\" class=\"select-option\"\n [value]=\"getDisplayName(judicial)\" (onSelectionChange)=\"onSelectionChange(judicial)\"\n [ngClass]=\"{'hide-autocomplete': !showAutocomplete}\">\n {{ getDisplayName(judicial) }}\n </mat-option>\n <mat-option class=\"select-option\"\n *ngIf=\"!displayedJudicialsDuplicationFiltered?.length && showAutocomplete && !searchInProgress\">\n {{ 'No results found' }}</mat-option>\n </mat-autocomplete>\n</div>\n",
1757
+ styles: [".hide-autocomplete{display:none}.mat-option:hover{background:#2596be}.mat-option.select-option:hover{background:#1d70b8;color:#fff}"]
1784
1758
  },] }
1785
1759
  ];
1786
- CookieBannerComponent.ctorParameters = () => [
1787
- { type: CookieService },
1788
- { type: undefined, decorators: [{ type: Inject, args: [windowToken,] }] }
1760
+ SearchJudicialsComponent.ctorParameters = () => [
1761
+ { type: FindAPersonService },
1762
+ { type: FormBuilder }
1789
1763
  ];
1790
- CookieBannerComponent.propDecorators = {
1791
- identifier: [{ type: Input }],
1792
- appName: [{ type: Input }],
1793
- rejectionNotifier: [{ type: Output }],
1794
- acceptanceNotifier: [{ type: Output }]
1764
+ SearchJudicialsComponent.propDecorators = {
1765
+ control: [{ type: Input }],
1766
+ disabled: [{ type: Input }],
1767
+ selectedJudicials: [{ type: Input }],
1768
+ submitted: [{ type: Input }],
1769
+ placeholderContent: [{ type: Input }],
1770
+ showAutocomplete: [{ type: Input }],
1771
+ displayedJudicials: [{ type: Input }],
1772
+ judicialChanged: [{ type: Output }],
1773
+ idValue: [{ type: Input }],
1774
+ errorMessage: [{ type: Input }],
1775
+ serviceId: [{ type: Input }],
1776
+ autoCompleteInputBox: [{ type: ViewChild, args: ['inputSelection', { read: ElementRef, static: true },] }]
1795
1777
  };
1796
1778
 
1797
- class LocationService {
1798
- constructor(http) {
1799
- this.http = http;
1800
- }
1801
- /**
1802
- * @description getAllLocations from service Ids/location type/search term
1803
- * @param serviceIds: SSCS | SSCS,IA split with ','
1804
- * @param locationType: optional | hearing | case_management
1805
- * @param searchTerm: any search term for postcode | site name | venue name |court name | court address etc.
1806
- * @return Observable<LocationByEPIMMSModel[]>: Array of locationModel in Observable
1807
- */
1808
- getAllLocations(serviceIds, locationType, searchTerm) {
1809
- return this.http.get(`api/locations/getLocations?serviceIds=${serviceIds}&locationType=${locationType}&searchTerm=${searchTerm}`);
1810
- }
1811
- /**
1812
- * @description searchLocations from service Ids/location type/search term
1813
- * @param serviceIds: BBA3 | BBA3,BFA1 split with ','
1814
- * @param locationType: optional | hearing | case_management
1815
- * @param searchTerm: any search term for postcode | site name | venue name |court name | court address etc.
1816
- * @return Observable<LocationByEPIMMSModel[]>: Array of locationModel in Observable
1817
- */
1818
- searchLocations(serviceIds, locationType, searchTerm) {
1819
- return this.http.get(`api/prd/location/getLocations?serviceIds=${serviceIds}&locationType=${locationType}&searchTerm=${searchTerm}`);
1820
- }
1821
- }
1822
- LocationService.ɵprov = i0.ɵɵdefineInjectable({ factory: function LocationService_Factory() { return new LocationService(i0.ɵɵinject(i1.HttpClient)); }, token: LocationService, providedIn: "root" });
1823
- LocationService.decorators = [
1824
- { type: Injectable, args: [{
1825
- providedIn: 'root'
1826
- },] }
1827
- ];
1828
- LocationService.ctorParameters = () => [
1829
- { type: HttpClient }
1830
- ];
1831
-
1832
- class SearchLocationComponent {
1833
- constructor(locationService, fb, cd) {
1779
+ class SearchVenueComponent {
1780
+ constructor(locationService, fb) {
1834
1781
  this.locationService = locationService;
1835
- this.fb = fb;
1836
- this.cd = cd;
1837
1782
  this.disabled = null;
1838
- this.singleMode = false;
1839
1783
  this.locationType = '';
1840
1784
  this.serviceIds = '';
1841
1785
  this.submitted = true;
1842
- this.delay = 500;
1843
1786
  this.showAutocomplete = false;
1844
- this.locations = [];
1845
- this.locationSelected = new EventEmitter();
1846
- this.locationInputChanged = new EventEmitter();
1847
- this.searchLocationChanged = new EventEmitter();
1787
+ this.locationChanged = new EventEmitter();
1848
1788
  this.minSearchCharacters = 3;
1849
- this.term = '';
1850
- this.pSelectedLocations = [];
1851
- this.pReset = true;
1852
- this.form = this.fb.group({
1853
- searchTerm: ['']
1789
+ this.keyUpSubject$ = new Subject();
1790
+ this.readyAfterContent = false;
1791
+ this.searchInProgress = false;
1792
+ this.findLocationFormGroup = fb.group({
1793
+ findLocationFormControl: [null],
1794
+ locationSelectedFormControl: [null]
1854
1795
  });
1796
+ this.selectedLocations = [];
1855
1797
  }
1856
- get reset() {
1857
- return this.pReset;
1858
- }
1859
- set reset(value) {
1860
- this.pReset = value;
1861
- this.resetSearchTerm();
1862
- }
1863
- get selectedLocations() {
1864
- return this.pSelectedLocations;
1865
- }
1866
- set selectedLocations(value) {
1867
- this.pSelectedLocations = value;
1798
+ ngAfterContentInit() {
1799
+ this.readyAfterContent = true;
1868
1800
  }
1869
1801
  ngOnInit() {
1870
- if (this.singleMode && this.selectedLocations.length > 0) {
1871
- const location = this.selectedLocations[0];
1872
- this.form.controls.searchTerm.patchValue(location.site_name, { emitEvent: false, onlySelf: true });
1802
+ this.displayedLocations = [];
1803
+ if (this.control) {
1804
+ if (this.findLocationFormGroup && this.findLocationFormGroup.controls) {
1805
+ this.findLocationFormGroup.controls.locationSelectedFormControl = this.control;
1806
+ }
1873
1807
  }
1874
- this.search();
1808
+ this.keyUpSubject$.pipe(debounceTime(500)).subscribe(searchValue => this.search(searchValue));
1875
1809
  }
1876
- filter(term) {
1877
- this.getLocations(term).pipe(map((locations) => this.removeSelectedLocations(locations)));
1810
+ onKeyDown() {
1811
+ this.locationChanged.emit();
1878
1812
  }
1879
- onSelectionChange(location) {
1880
- this.form.controls.searchTerm.patchValue(location.site_name, { emitEvent: false, onlySelf: true });
1881
- this.locationSelected.emit(location);
1813
+ onKeyUp(event) {
1814
+ this.showAutocomplete = false;
1815
+ this.keyUpSubject$.next(event.target.value);
1882
1816
  }
1883
- search() {
1884
- this.form.controls.searchTerm.valueChanges
1885
- .pipe(tap((term) => this.locationInputChanged.next(term)), tap(() => this.locations = []), tap((term) => this.term = term), filter(term => !!term && term.length >= this.minSearchCharacters), debounceTime(this.delay), mergeMap(value => this.getLocations(value)), map((locations) => this.removeSelectedLocations(locations))).subscribe(locations => {
1886
- this.locations = locations;
1887
- this.cd.markForCheck();
1888
- if (locations.length === 1 && this.term === locations[0].site_name && !this.singleMode) {
1889
- this.locationSelected.emit(locations[0]);
1817
+ onFocus() {
1818
+ this.showAutocomplete = false;
1819
+ }
1820
+ get displayedLocationsDuplicationFiltered() {
1821
+ return this.displayedLocations.filter(location => !this.selectedLocations.map(selectedLocation => selectedLocation.epimms_id).includes(location.epimms_id) && location.court_name);
1822
+ }
1823
+ filter(term) {
1824
+ this.searchLocations(term).pipe(mergeMap((apiData) => {
1825
+ const apiFilter = apiData.filter(apiLocation => !this.selectedLocations.map(selectedLocation => selectedLocation.epimms_id).includes(apiLocation.epimms_id));
1826
+ this.displayedLocations = apiFilter;
1827
+ this.searchInProgress = false;
1828
+ return apiFilter;
1829
+ })).subscribe(location => {
1830
+ if (term === location.court_name) {
1831
+ this.findLocationFormGroup.controls.locationSelectedFormControl.setValue(location);
1832
+ this.displayedLocations = [];
1833
+ this.locationChanged.emit(location);
1890
1834
  this.showAutocomplete = false;
1891
- return;
1892
1835
  }
1893
- this.showAutocomplete = true;
1836
+ this.searchInProgress = false;
1894
1837
  });
1895
1838
  }
1896
- onInput() {
1897
- this.searchLocationChanged.emit();
1839
+ onSelectionChange(selection) {
1840
+ if (this.findLocationFormGroup.controls.findLocationFormControl instanceof FormArray) {
1841
+ this.findLocationFormGroup.controls.locationSelectedFormControl.push(new FormControl(selection.epimms_id));
1842
+ }
1843
+ else {
1844
+ this.findLocationFormGroup.controls.locationSelectedFormControl.setValue(selection);
1845
+ }
1846
+ this.locationChanged.emit(selection);
1898
1847
  }
1899
- getLocations(term) {
1900
- return this.locationService.getAllLocations(this.serviceIds, this.locationType, term);
1848
+ search(currentValue) {
1849
+ this.searchInProgress = true;
1850
+ this.showAutocomplete = !!currentValue && (currentValue.length >= this.minSearchCharacters);
1851
+ if (!currentValue || !currentValue.length) {
1852
+ this.findLocationFormGroup.controls.locationSelectedFormControl.markAsPristine();
1853
+ this.findLocationFormGroup.controls.locationSelectedFormControl.reset();
1854
+ }
1855
+ if (this.showAutocomplete) {
1856
+ this.filter(currentValue);
1857
+ }
1858
+ else {
1859
+ this.searchInProgress = false;
1860
+ }
1901
1861
  }
1902
- resetSearchTerm() {
1903
- this.form.controls.searchTerm.patchValue('', { emitEvent: false, onlySelf: true });
1862
+ getDisplayName(selectedLocation) {
1863
+ return selectedLocation.court_name;
1904
1864
  }
1905
- removeSelectedLocations(locations) {
1906
- if (this.singleMode) {
1907
- return locations;
1908
- }
1909
- return locations.filter(location => !this.selectedLocations.map(selectedLocation => selectedLocation.epimms_id).includes(location.epimms_id) && location.site_name);
1865
+ searchLocations(term) {
1866
+ return this.locationService.searchLocations(this.serviceIds, this.locationType, term);
1867
+ }
1868
+ getControlCourtNameValue() {
1869
+ return this.findLocationFormGroup && this.findLocationFormGroup.controls && this.findLocationFormGroup.controls.locationSelectedFormControl.value ?
1870
+ this.findLocationFormGroup.controls.locationSelectedFormControl.value.court_name : '';
1910
1871
  }
1911
1872
  }
1912
- SearchLocationComponent.decorators = [
1873
+ SearchVenueComponent.decorators = [
1913
1874
  { type: Component, args: [{
1914
- selector: 'exui-search-location',
1915
- template: "<div class=\"auto-complete-container\">\n <input\n id=\"inputLocationSearch\"\n (input)=\"onInput()\"\n [formControl]=\"form.controls.searchTerm\"\n [matAutocomplete]=\"autoSearchLocation\"\n class=\"govuk-input\"\n [attr.disabled]=\"disabled\">\n <mat-autocomplete class=\"mat-autocomplete-panel-extend\" autoActiveFirstOption #autoSearchLocation=\"matAutocomplete\">\n <mat-option *ngFor=\"let location of locations\"\n (onSelectionChange)=\"onSelectionChange(location)\">\n {{ location.site_name }}\n </mat-option>\n <mat-option *ngIf=\"!locations.length && showAutocomplete && term && term.length >= this.minSearchCharacters\">No results found</mat-option>\n </mat-autocomplete>\n</div>\n",
1916
- styles: [".autocomplete__input--show-all-values{padding:5px 34px 5px 5px;cursor:pointer}.autocomplete__dropdown-arrow-down{z-index:-1;display:inline-block;position:absolute;right:8px;width:24px;height:24px;top:10px}.autocomplete__menu{background-color:#fff;border:2px solid #0b0c0c;border-top:0;color:#0b0c0c;margin:0;max-height:342px;overflow-x:hidden;padding:0;width:100%;width:calc(100% - 4px)}.autocomplete__menu--visible{display:block}.autocomplete__menu--hidden{display:none}.autocomplete__menu--overlay{box-shadow:0 2px 6px rgba(0,0,0,.256863);left:0;position:absolute;top:100%;z-index:100}.autocomplete__menu--inline{position:relative}.autocomplete__option{border-left-width:0;border-bottom:1px solid #b1b4b6;border-right-width:0;border-top-width:1px;cursor:pointer;display:block;position:relative}.autocomplete__option>*{pointer-events:none}.autocomplete__option:first-of-type{border-top-width:0}.autocomplete__option:last-of-type{border-bottom-width:0}.autocomplete__option--odd{background-color:#fafafa}.autocomplete__option--focused,.autocomplete__option:hover{background-color:#1d70b8;border-color:#1d70b8;color:#fff;outline:0}.autocomplete__option--no-results{background-color:#fafafa;color:#646b6f;cursor:not-allowed}.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.25}.autocomplete__hint,.autocomplete__option{padding:5px}@media (min-width:641px){.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.31579}}.div-action{display:inline-block}.add-location{display:inline}.remove-location-button{margin:5px}.hide-autocomplete{display:none}.auto-complete-container{min-width:550px;display:inline-block;margin-right:4px}.autocomplete__input{line-height:24px;font-size:19px}"]
1875
+ selector: 'xuilib-search-venue',
1876
+ template: "<div class=\"auto-complete-container\">\n <div *ngIf=\"readyAfterContent\" class=\"autocomplete__wrapper\">\n <input\n [formControl]=\"findLocationFormGroup.controls.findLocationFormControl\"\n [matAutocomplete]=\"autoSearchLocation\"\n (keydown)=\"onKeyDown()\"\n (keyup)=\"onKeyUp($event)\"\n (focus)=\"onFocus()\"\n class=\"autocomplete__input autocomplete__input--default search-box\"\n [attr.disabled]=\"!disabled ? null: disabled\"\n [value]=\"getControlCourtNameValue()\"\n #inputSelectedLocation>\n <mat-autocomplete class=\"mat-autocomplete-panel-extend\" autoActiveFirstOption #autoSearchLocation=\"matAutocomplete\">\n <mat-option *ngFor=\"let location of displayedLocationsDuplicationFiltered\"\n [value]=\"getDisplayName(location)\"\n (onSelectionChange)=\"onSelectionChange(location)\"\n [ngClass]=\"{'hide-autocomplete': !showAutocomplete}\">\n {{ getDisplayName(location) }}\n </mat-option>\n <mat-option *ngIf=\"!displayedLocationsDuplicationFiltered?.length && showAutocomplete && !searchInProgress\">{{ 'No results found' }}</mat-option>\n </mat-autocomplete>\n </div>\n</div>\n",
1877
+ styles: [".autocomplete__input{-webkit-appearance:none;border:2px solid #0b0c0c;border-radius:0;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;margin-bottom:0;width:100%;line-height:24px;font-size:19px;background-color:transparent;position:relative}.autocomplete__hint{color:#b1b4b6;position:absolute}.autocomplete__input--default{padding:5px}.autocomplete__input--focused{outline:3px solid #fd0;outline-offset:0;box-shadow:inset 0 0 0 2px}.autocomplete__input--show-all-values{padding:5px 34px 5px 5px;cursor:pointer}.autocomplete__dropdown-arrow-down{z-index:-1;display:inline-block;position:absolute;right:8px;width:24px;height:24px;top:10px}.autocomplete__menu{background-color:#fff;border:2px solid #0b0c0c;border-top:0;color:#0b0c0c;margin:0;max-height:342px;overflow-x:hidden;padding:0;width:100%;width:calc(100% - 4px)}.autocomplete__menu--visible{display:block}.autocomplete__menu--hidden{display:none}.autocomplete__menu--overlay{box-shadow:0 2px 6px rgba(0,0,0,.256863);left:0;position:absolute;top:100%;z-index:100}.autocomplete__menu--inline{position:relative}.autocomplete__option{border-left-width:0;border-bottom:1px solid #b1b4b6;border-right-width:0;border-top-width:1px;cursor:pointer;display:block;position:relative}.autocomplete__option>*{pointer-events:none}.autocomplete__option:first-of-type{border-top-width:0}.autocomplete__option:last-of-type{border-bottom-width:0}.autocomplete__option--odd{background-color:#fafafa}.autocomplete__option--focused,.autocomplete__option:hover{background-color:#1d70b8;border-color:#1d70b8;color:#fff;outline:0}.autocomplete__option--no-results{background-color:#fafafa;color:#646b6f;cursor:not-allowed}.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.25}.autocomplete__hint,.autocomplete__option{padding:5px}@media (min-width:641px){.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.31579}}.div-action{display:inline-block}.add-location{display:inline}.remove-location-button{margin:5px}.hide-autocomplete{display:none}.auto-complete-container{min-width:550px;display:inline-block;margin-right:4px}"]
1917
1878
  },] }
1918
1879
  ];
1919
- SearchLocationComponent.ctorParameters = () => [
1880
+ SearchVenueComponent.ctorParameters = () => [
1920
1881
  { type: LocationService },
1921
- { type: FormBuilder },
1922
- { type: ChangeDetectorRef }
1882
+ { type: FormBuilder }
1923
1883
  ];
1924
- SearchLocationComponent.propDecorators = {
1884
+ SearchVenueComponent.propDecorators = {
1925
1885
  control: [{ type: Input }],
1926
1886
  disabled: [{ type: Input }],
1927
- singleMode: [{ type: Input }],
1928
1887
  locationType: [{ type: Input }],
1888
+ selectedLocations: [{ type: Input }],
1929
1889
  serviceIds: [{ type: Input }],
1930
1890
  submitted: [{ type: Input }],
1931
- delay: [{ type: Input }],
1932
- form: [{ type: Input }],
1891
+ autoCompleteInputBox: [{ type: ViewChild, args: ['inputSelectedLocation', { read: ElementRef },] }],
1933
1892
  showAutocomplete: [{ type: Input }],
1934
- locations: [{ type: Input }],
1935
- locationSelected: [{ type: Output }],
1936
- locationInputChanged: [{ type: Output }],
1937
- searchLocationChanged: [{ type: Output }],
1938
- reset: [{ type: Input }],
1939
- selectedLocations: [{ type: Input }]
1893
+ displayedLocations: [{ type: Input }],
1894
+ locationChanged: [{ type: Output }]
1940
1895
  };
1941
1896
 
1942
- class FindLocationComponent {
1897
+ class CaseSharingStateService {
1943
1898
  constructor() {
1944
- this.locationFieldChanged = new EventEmitter();
1945
- this.selectedLocations = [];
1946
- this.submitted = true;
1947
- this.enableAddLocationButton = true;
1948
- this.locationTitle = 'Search for a location by name';
1949
- this.disableInputField = false;
1950
- this.locations = [];
1951
- this.tempSelectedLocation = null;
1952
- this.serviceIds = 'SSCS,IA';
1953
- this.pServices = [];
1954
- this.pDisabled = false;
1899
+ this.caseState = [];
1900
+ this.subject = new BehaviorSubject(this.caseState);
1955
1901
  }
1956
- get disabled() {
1957
- return this.pDisabled;
1902
+ get state() {
1903
+ return this.subject.asObservable().pipe(distinctUntilChanged());
1958
1904
  }
1959
- set disabled(value) {
1960
- if (value) {
1961
- this.searchLocationComponent.resetSearchTerm();
1962
- this.removeSelectedValues();
1963
- }
1964
- this.pDisabled = this.disableInputField === true ? true : null;
1905
+ setCases(cases) {
1906
+ this.caseState = [];
1907
+ cases.forEach(aCase => {
1908
+ this.caseState.push({ caseId: aCase.caseId, caseTitle: aCase.caseTitle, caseTypeId: aCase.caseTypeId, roles: aCase.roles,
1909
+ sharedWith: aCase.sharedWith, pendingShares: aCase.pendingShares, pendingUnshares: aCase.pendingUnshares });
1910
+ });
1911
+ this.subject.next(this.caseState);
1965
1912
  }
1966
- get services() {
1967
- return this.pServices;
1913
+ getCases() {
1914
+ return this.caseState;
1968
1915
  }
1969
- set services(value) {
1970
- this.pServices = value;
1971
- const field = this.fields.find(f => f.name === this.field.findLocationField);
1972
- if (field) {
1973
- if (typeof value === 'string') {
1974
- this.serviceIds = value;
1916
+ requestShare(user) {
1917
+ const oldSharedCases = this.caseState.slice();
1918
+ const newSharedCases = [];
1919
+ for (const sharedCase of oldSharedCases) {
1920
+ if (!sharedCase.pendingShares) {
1921
+ sharedCase.pendingShares = [];
1922
+ }
1923
+ const newPendingShares = sharedCase.pendingShares.slice();
1924
+ if (!sharedCase.pendingUnshares) {
1925
+ sharedCase.pendingUnshares = [];
1926
+ }
1927
+ const newPendingUnshares = sharedCase.pendingUnshares.slice();
1928
+ if (!this.userHasAccess(sharedCase, user)) {
1929
+ if (!newPendingShares.some(u => u.email === user.email)) {
1930
+ newPendingShares.push(user);
1931
+ }
1975
1932
  }
1976
1933
  else {
1977
- this.serviceIds = getValues(field.options, value).filter(x => x !== 'services_all').join(',');
1934
+ for (let u = 0, ul = newPendingUnshares.length; u < ul; u++) {
1935
+ if (newPendingUnshares[u].email === user.email) {
1936
+ newPendingUnshares.splice(u, 1);
1937
+ break;
1938
+ }
1939
+ }
1978
1940
  }
1941
+ const newSharedCase = Object.assign(Object.assign({}, sharedCase), { pendingUnshares: newPendingUnshares, pendingShares: newPendingShares });
1942
+ newSharedCases.push(newSharedCase);
1979
1943
  }
1944
+ this.subject.next(newSharedCases);
1945
+ return newSharedCases;
1980
1946
  }
1981
- addLocation() {
1982
- if (this.tempSelectedLocation) {
1983
- this.selectedLocations = [...this.selectedLocations, this.tempSelectedLocation];
1984
- this.addSelectedLocationsToForm([this.tempSelectedLocation]);
1985
- this.tempSelectedLocation = null;
1986
- this.locations = [];
1987
- this.searchLocationComponent.resetSearchTerm();
1947
+ requestUnshare(caseId, user) {
1948
+ const newSharedCases = [];
1949
+ for (const sharedCase of this.caseState) {
1950
+ if (sharedCase.caseId === caseId) {
1951
+ if (!sharedCase.pendingUnshares) {
1952
+ sharedCase.pendingUnshares = [];
1953
+ }
1954
+ const newPendingUnshares = sharedCase.pendingUnshares.slice();
1955
+ if (newPendingUnshares) {
1956
+ if (!newPendingUnshares.some(u => u.email === user.email)) {
1957
+ newPendingUnshares.push(user);
1958
+ }
1959
+ }
1960
+ else {
1961
+ newPendingUnshares.push(user);
1962
+ }
1963
+ const newSharedCase = Object.assign(Object.assign({}, sharedCase), { pendingUnshares: newPendingUnshares });
1964
+ newSharedCases.push(newSharedCase);
1965
+ }
1966
+ else {
1967
+ newSharedCases.push(sharedCase);
1968
+ }
1988
1969
  }
1970
+ this.subject.next(newSharedCases);
1971
+ return;
1989
1972
  }
1990
- removeLocation(location) {
1991
- if (location.epimms_id) {
1992
- this.selectedLocations = this.selectedLocations.filter(selectedLocation => selectedLocation.epimms_id !== location.epimms_id);
1993
- const formArray = this.form.get(this.field.name);
1994
- const index = formArray.value.findIndex(selectedLocation => selectedLocation.epimms_id === location.epimms_id);
1995
- if (index > -1) {
1996
- formArray.removeAt(index);
1973
+ requestCancel(caseId, user) {
1974
+ const newSharedCases = [];
1975
+ for (const sharedCase of this.caseState) {
1976
+ if (sharedCase.caseId === caseId) {
1977
+ if (!sharedCase.pendingUnshares) {
1978
+ sharedCase.pendingUnshares = [];
1979
+ }
1980
+ const newPendingUnshares = sharedCase.pendingUnshares.slice();
1981
+ for (let iPendingUnshares = 0; iPendingUnshares < newPendingUnshares.length; iPendingUnshares++) {
1982
+ if (newPendingUnshares[iPendingUnshares].email === user.email) {
1983
+ newPendingUnshares.splice(iPendingUnshares, 1);
1984
+ break;
1985
+ }
1986
+ }
1987
+ if (!sharedCase.pendingShares) {
1988
+ sharedCase.pendingShares = [];
1989
+ }
1990
+ const newPendingShares = sharedCase.pendingShares.slice();
1991
+ for (let iPendingShares = 0; iPendingShares < newPendingShares.length; iPendingShares++) {
1992
+ if (newPendingShares[iPendingShares].email === user.email) {
1993
+ newPendingShares.splice(iPendingShares, 1);
1994
+ break;
1995
+ }
1996
+ }
1997
+ const newSharedCase = Object.assign(Object.assign({}, sharedCase), { pendingUnshares: newPendingUnshares, pendingShares: newPendingShares });
1998
+ newSharedCases.push(newSharedCase);
1999
+ }
2000
+ else {
2001
+ newSharedCases.push(sharedCase);
1997
2002
  }
1998
2003
  }
2004
+ this.subject.next(newSharedCases);
2005
+ return;
1999
2006
  }
2000
- onInputChanged(term) {
2001
- // if the filter is in single mode clear the selected locations
2002
- if (typeof term === 'string' && this.field.maxSelected === 1) {
2003
- this.removeSelectedValues();
2007
+ removeCase(caseId) {
2008
+ for (let i = 0, l = this.caseState.length; i < l; i++) {
2009
+ if (this.caseState[i].caseId === caseId) {
2010
+ this.caseState.splice(i, 1);
2011
+ this.subject.next(this.caseState);
2012
+ return;
2013
+ }
2004
2014
  }
2005
2015
  }
2006
- onSearchInputChanged() {
2007
- this.locationFieldChanged.emit();
2008
- }
2009
- onLocationSelected(location) {
2010
- if (this.field.maxSelected === 1) {
2011
- this.removeSelectedValues();
2012
- this.addSelectedLocationsToForm([location]);
2016
+ userHasAccess(c, user) {
2017
+ if (!c.sharedWith) {
2018
+ return false;
2013
2019
  }
2014
- else {
2015
- if (!this.selectedLocations.find(x => x.epimms_id === location.epimms_id)) {
2016
- if (location.epimms_id) {
2017
- this.tempSelectedLocation = location;
2018
- }
2020
+ for (let i = 0, l = c.sharedWith.length; i < l; i++) {
2021
+ if (c.sharedWith[i].email === user.email) {
2022
+ return true;
2019
2023
  }
2020
2024
  }
2025
+ return false;
2021
2026
  }
2022
- removeSelectedValues() {
2023
- const formArray = this.form.get(this.field.name);
2024
- for (let i = 0; i < formArray.length; i++) {
2025
- formArray.removeAt(i);
2026
- }
2027
- this.selectedLocations = [];
2027
+ }
2028
+ CaseSharingStateService.ɵprov = i0.ɵɵdefineInjectable({ factory: function CaseSharingStateService_Factory() { return new CaseSharingStateService(); }, token: CaseSharingStateService, providedIn: "root" });
2029
+ CaseSharingStateService.decorators = [
2030
+ { type: Injectable, args: [{
2031
+ providedIn: 'root'
2032
+ },] }
2033
+ ];
2034
+ CaseSharingStateService.ctorParameters = () => [];
2035
+
2036
+ class SelectedCaseConfirmComponent {
2037
+ constructor(stateService) {
2038
+ this.stateService = stateService;
2039
+ this.changeLink = '';
2028
2040
  }
2029
- addSelectedLocationsToForm(locations) {
2030
- const formArray = this.form.get(this.field.name);
2031
- for (const location of locations) {
2032
- formArray.push(new FormControl(location));
2041
+ ngOnInit() {
2042
+ this.shareCases$ = this.stateService.state;
2043
+ this.shareCases$.subscribe(shareCases => this.shareCases = shareCases);
2044
+ }
2045
+ trackByUserId(user) {
2046
+ return user.idamId;
2047
+ }
2048
+ showUserAccessBlock() {
2049
+ if (this.sharedCase.pendingShares && this.sharedCase.pendingShares.length > 0) {
2050
+ return true;
2033
2051
  }
2052
+ return this.sharedCase.pendingUnshares && this.sharedCase.pendingUnshares.length > 0;
2034
2053
  }
2035
2054
  }
2036
- FindLocationComponent.decorators = [
2055
+ SelectedCaseConfirmComponent.decorators = [
2037
2056
  { type: Component, args: [{
2038
- selector: 'xuilib-find-location',
2039
- template: "<div class=\"location-picker-custom\">\n <div class=\"search-location\">\n <div>\n <label id=\"input-selected-location-label\" *ngIf=\"locationTitle\">{{locationTitle}}</label>\n </div>\n <exui-search-location class=\"search-location\"\n [locations]=\"locations\"\n [selectedLocations]=\"selectedLocations\"\n [singleMode]=\"field.maxSelected === 1\"\n [delay]=\"300\"\n [disabled]=\"disabled\"\n [serviceIds]=\"serviceIds\"\n (locationInputChanged)=\"onInputChanged($event)\"\n (locationSelected)=\"onLocationSelected($event)\"\n (searchLocationChanged)=\"onSearchInputChanged()\"\n [locationType]=\"'case-management'\"></exui-search-location>\n <a href=\"javascript:void(0)\" (click)=\"addLocation()\" class=\"govuk-button\" data-module=\"govuk-button\" *ngIf=\"enableAddLocationButton\">\n Add location\n </a>\n </div>\n <ul class=\"hmcts-filter-tags selection-container\" *ngIf=\"field.maxSelected != 1\">\n <li class=\"location-selection\" *ngFor=\"let selection of selectedLocations\">\n <a class=\"hmcts-filter__tag\" (click)=\"removeLocation(selection)\" href=\"javascript:void(0)\">\n {{ selection.site_name }}\n </a>\n </li>\n </ul>\n</div>\n",
2040
- styles: [""]
2057
+ selector: 'xuilib-selected-case-confirm',
2058
+ template: "<div id=\"user-access-block-{{ sharedCase.caseId }}\" *ngIf=\"showUserAccessBlock()\">\n <h2 class=\"govuk-heading-m case-share-confirm__title\">{{ sharedCase.caseTitle }}</h2>\n <div class=\"case-share-confirm__caption-area\">\n <div class=\"govuk-caption-m case-share-confirm__caption\">\n {{ sharedCase.caseId }}\n </div>\n <a [routerLink]=\"changeLink\" class=\"case-share-confirm__change-link govuk-link govuk-!-font-size-19\">Change</a>\n </div>\n <table class=\"govuk-table\">\n <thead class=\"govuk-table__head\">\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Name</th>\n <th class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Email address</th>\n <th class=\"govuk-table__header govuk-table-column-actions\" scope=\"col\">Actions</th>\n </tr>\n </thead>\n <tbody class=\"govuk-table__body\">\n <tr class=\"govuk-table__row\" *ngFor=\"let user of sharedCase.pendingShares; trackBy: trackByUserId\">\n <td class=\"govuk-table__cell\">{{ user.firstName + ' ' + user.lastName }}</td>\n <td class=\"govuk-table__cell\">{{ user.email }}</td>\n <td class=\"govuk-table__cell\">\n <span class=\"hmcts-badge\">To be added</span>\n </td>\n </tr>\n <tr class=\"govuk-table__row\" *ngFor=\"let user of sharedCase.pendingUnshares; trackBy: trackByUserId\">\n <td class=\"govuk-table__cell\">{{ user.firstName + ' ' + user.lastName }}</td>\n <td class=\"govuk-table__cell\">{{ user.email }}</td>\n <td class=\"govuk-table__cell\">\n <span class=\"hmcts-badge hmcts-badge--red\">to be removed</span>\n </td>\n </tr>\n </tbody>\n </table>\n</div>\n",
2059
+ styles: [".case-share-confirm__title{margin-bottom:0}.case-share-confirm__caption-area{border-bottom:1px solid #b1b4b6;padding-bottom:10px;display:inline-block;width:100%;clear:both}.case-share-confirm__caption{float:left}.case-share-confirm__change-link{float:right}.govuk-table-column-header{width:45%}.govuk-table-column-actions{width:10%}"]
2041
2060
  },] }
2042
2061
  ];
2043
- FindLocationComponent.propDecorators = {
2044
- locationFieldChanged: [{ type: Output }],
2045
- selectedLocations: [{ type: Input }],
2046
- submitted: [{ type: Input }],
2047
- enableAddLocationButton: [{ type: Input }],
2048
- form: [{ type: Input }],
2049
- field: [{ type: Input }],
2050
- fields: [{ type: Input }],
2051
- locationTitle: [{ type: Input }],
2052
- disableInputField: [{ type: Input }],
2053
- searchLocationComponent: [{ type: ViewChild, args: [SearchLocationComponent, { static: true },] }],
2054
- disabled: [{ type: Input }],
2055
- services: [{ type: Input }]
2062
+ SelectedCaseConfirmComponent.ctorParameters = () => [
2063
+ { type: CaseSharingStateService }
2064
+ ];
2065
+ SelectedCaseConfirmComponent.propDecorators = {
2066
+ sharedCase: [{ type: Input }],
2067
+ changeLink: [{ type: Input }]
2056
2068
  };
2057
2069
 
2058
- class PaginationComponent {
2059
- constructor() {
2060
- this.previousPage = new EventEmitter();
2061
- this.nextPage = new EventEmitter();
2070
+ class SelectedCaseListComponent {
2071
+ constructor(stateService) {
2072
+ this.stateService = stateService;
2073
+ this.shareCases = [];
2074
+ this.toConfirm = false;
2075
+ this.changeLink = '';
2076
+ this.unselect = new EventEmitter();
2077
+ this.synchronizeStore = new EventEmitter();
2078
+ }
2079
+ ngOnInit() {
2080
+ this.shareCases$ = this.stateService.state;
2081
+ this.shareCases$.subscribe(shareCases => this.shareCases = shareCases);
2082
+ }
2083
+ onUnselect(sharedCase) {
2084
+ this.unselect.emit(sharedCase);
2062
2085
  }
2063
- onPrevious() {
2064
- this.previousPage.emit(null);
2086
+ onSynchronizeStore(event) {
2087
+ this.synchronizeStore.emit(event);
2065
2088
  }
2066
- onNext() {
2067
- this.nextPage.emit(null);
2089
+ trackByCaseId(sharedCase) {
2090
+ return sharedCase.caseId;
2068
2091
  }
2069
2092
  }
2070
- PaginationComponent.decorators = [
2093
+ SelectedCaseListComponent.decorators = [
2071
2094
  { type: Component, args: [{
2072
- selector: 'xuilib-pagination',
2073
- template: "<nav class=\"hmcts-pagination\" id=\"pagination-label\">\n\n <p class=\"govuk-visually-hidden\" aria-labelledby=\"pagination-label\">Pagination navigation</p>\n\n <ul class=\"hmcts-pagination__list\">\n <li class=\"hmcts-pagination__item hmcts-pagination__item--prev\">\n <a *ngIf=\"firstRecord > 1; else noPrevious\" class=\"hmcts-pagination__link\" (click)=\"onPrevious()\" href=\"javascript:void(0)\">\n Previous page\n </a>\n <ng-template #noPrevious>\n <span class=\"hmcts-pagination__link\">Previous page</span>\n </ng-template>\n </li>\n\n <li class=\"hmcts-pagination__item hmcts-pagination__item--next\">\n <a *ngIf=\"moreItems; else noNext\" class=\"hmcts-pagination__link\" (click)=\"onNext()\" href=\"javascript:void(0)\">Next page</a>\n <ng-template #noNext>\n <span class=\"hmcts-pagination__link\">Next page</span>\n </ng-template>\n </li>\n </ul>\n</nav>\n",
2074
- styles: ["span.hmcts-pagination__link:hover{color:revert}"]
2095
+ selector: 'xuilib-selected-case-list',
2096
+ template: "<ng-container *ngIf=\"!toConfirm\">\n <xuilib-selected-case\n *ngFor=\"let sharedCase of (shareCases$ | async); trackBy: trackByCaseId\"\n [sharedCase]=\"sharedCase\"\n [removeUserFromCaseToggleOn]=\"removeUserFromCaseToggleOn\"\n (unselect)=\"onUnselect($event)\"\n (synchronizeStore)=\"onSynchronizeStore($event)\"\n >\n </xuilib-selected-case>\n</ng-container>\n\n<ng-container *ngIf=\"toConfirm\">\n <xuilib-selected-case-confirm\n *ngFor=\"let sharedCase of (shareCases$ | async); trackBy: trackByCaseId\"\n [sharedCase]=\"sharedCase\"\n [changeLink]=\"changeLink\">\n </xuilib-selected-case-confirm>\n</ng-container>\n",
2097
+ styles: [""]
2075
2098
  },] }
2076
2099
  ];
2077
- PaginationComponent.ctorParameters = () => [];
2078
- PaginationComponent.propDecorators = {
2079
- moreItems: [{ type: Input }],
2080
- firstRecord: [{ type: Input }],
2081
- previousPage: [{ type: Output }],
2082
- nextPage: [{ type: Output }]
2100
+ SelectedCaseListComponent.ctorParameters = () => [
2101
+ { type: CaseSharingStateService }
2102
+ ];
2103
+ SelectedCaseListComponent.propDecorators = {
2104
+ shareCases$: [{ type: Input }],
2105
+ removeUserFromCaseToggleOn: [{ type: Input }],
2106
+ toConfirm: [{ type: Input }],
2107
+ changeLink: [{ type: Input }],
2108
+ unselect: [{ type: Output }],
2109
+ synchronizeStore: [{ type: Output }]
2083
2110
  };
2084
2111
 
2085
- class SearchVenueComponent {
2086
- constructor(locationService, fb) {
2087
- this.locationService = locationService;
2088
- this.disabled = null;
2089
- this.locationType = '';
2090
- this.serviceIds = '';
2091
- this.submitted = true;
2092
- this.showAutocomplete = false;
2093
- this.locationChanged = new EventEmitter();
2094
- this.minSearchCharacters = 3;
2095
- this.keyUpSubject$ = new Subject();
2096
- this.readyAfterContent = false;
2097
- this.searchInProgress = false;
2098
- this.findLocationFormGroup = fb.group({
2099
- findLocationFormControl: [null],
2100
- locationSelectedFormControl: [null]
2101
- });
2102
- this.selectedLocations = [];
2103
- }
2104
- ngAfterContentInit() {
2105
- this.readyAfterContent = true;
2112
+ class SelectedCaseComponent {
2113
+ constructor(stateService) {
2114
+ this.stateService = stateService;
2115
+ this.opened = false;
2116
+ this.unselect = new EventEmitter();
2117
+ this.synchronizeStore = new EventEmitter();
2106
2118
  }
2107
2119
  ngOnInit() {
2108
- this.displayedLocations = [];
2109
- if (this.control) {
2110
- if (this.findLocationFormGroup && this.findLocationFormGroup.controls) {
2111
- this.findLocationFormGroup.controls.locationSelectedFormControl = this.control;
2112
- }
2120
+ this.shareCases$ = this.stateService.state;
2121
+ this.shareCases$.subscribe(shareCases => this.shareCases = shareCases);
2122
+ }
2123
+ ngOnChanges(changes) {
2124
+ if (changes.sharedCase) {
2125
+ const sharedWith = this.sharedCase.sharedWith ? this.sharedCase.sharedWith : [];
2126
+ const pendingShares = this.sharedCase.pendingShares ? this.sharedCase.pendingShares : [];
2127
+ this.combinedSortedShares = this.combineAndSortShares(sharedWith, pendingShares);
2113
2128
  }
2114
- this.keyUpSubject$.pipe(debounceTime(500)).subscribe(searchValue => this.search(searchValue));
2115
2129
  }
2116
- onKeyDown() {
2117
- this.locationChanged.emit();
2130
+ onUnselect() {
2131
+ this.unselect.emit(this.sharedCase);
2118
2132
  }
2119
- onKeyUp(event) {
2120
- this.showAutocomplete = false;
2121
- this.keyUpSubject$.next(event.target.value);
2133
+ onDeselect(c) {
2134
+ this.unselect.emit(c);
2122
2135
  }
2123
- onFocus() {
2124
- this.showAutocomplete = false;
2136
+ trackByUserId(user) {
2137
+ return user.idamId;
2125
2138
  }
2126
- get displayedLocationsDuplicationFiltered() {
2127
- return this.displayedLocations.filter(location => !this.selectedLocations.map(selectedLocation => selectedLocation.epimms_id).includes(location.epimms_id) && location.court_name);
2139
+ canRemove(caseId, user) {
2140
+ return this.shareCases$.pipe(map(cases => {
2141
+ if (this.removeUserFromCaseToggleOn) {
2142
+ for (const aCase of cases) {
2143
+ if (aCase.caseId === caseId) {
2144
+ if (aCase.pendingUnshares && aCase.pendingUnshares.some(u => u.idamId === user.idamId)) {
2145
+ return false;
2146
+ }
2147
+ if (aCase.sharedWith && aCase.sharedWith.some(u => u.idamId === user.idamId)) {
2148
+ return true;
2149
+ }
2150
+ }
2151
+ }
2152
+ }
2153
+ return false;
2154
+ }));
2128
2155
  }
2129
- filter(term) {
2130
- this.searchLocations(term).pipe(mergeMap((apiData) => {
2131
- const apiFilter = apiData.filter(apiLocation => !this.selectedLocations.map(selectedLocation => selectedLocation.epimms_id).includes(apiLocation.epimms_id));
2132
- this.displayedLocations = apiFilter;
2133
- this.searchInProgress = false;
2134
- return apiFilter;
2135
- })).subscribe(location => {
2136
- if (term === location.court_name) {
2137
- this.findLocationFormGroup.controls.locationSelectedFormControl.setValue(location);
2138
- this.displayedLocations = [];
2139
- this.locationChanged.emit(location);
2140
- this.showAutocomplete = false;
2156
+ canCancel(caseId, user) {
2157
+ return this.shareCases$.pipe(map(cases => {
2158
+ for (const aCase of cases) {
2159
+ if (aCase.caseId === caseId) {
2160
+ if (aCase.pendingShares && aCase.pendingShares.some(u => u.idamId === user.idamId)) {
2161
+ return true;
2162
+ }
2163
+ if (aCase.pendingUnshares && aCase.pendingUnshares.some(u => u.idamId === user.idamId)) {
2164
+ return true;
2165
+ }
2166
+ return false;
2167
+ }
2141
2168
  }
2142
- this.searchInProgress = false;
2143
- });
2169
+ }));
2144
2170
  }
2145
- onSelectionChange(selection) {
2146
- if (this.findLocationFormGroup.controls.findLocationFormControl instanceof FormArray) {
2147
- this.findLocationFormGroup.controls.locationSelectedFormControl.push(new FormControl(selection.epimms_id));
2171
+ isToBeRemoved(caseId, user) {
2172
+ return this.shareCases$.pipe(map(cases => {
2173
+ for (const aCase of cases) {
2174
+ if (aCase.caseId === caseId) {
2175
+ return aCase.pendingUnshares && aCase.pendingUnshares.some(u => u.idamId === user.idamId);
2176
+ }
2177
+ }
2178
+ }));
2179
+ }
2180
+ isToBeAdded(caseId, user) {
2181
+ return this.shareCases$.pipe(map(cases => {
2182
+ for (const aCase of cases) {
2183
+ if (aCase.caseId === caseId) {
2184
+ return aCase.pendingShares && aCase.pendingShares.some(u => u.idamId === user.idamId);
2185
+ }
2186
+ }
2187
+ }));
2188
+ }
2189
+ onRemove(user, sharedCase) {
2190
+ this.stateService.requestUnshare(sharedCase.caseId, user);
2191
+ this.synchronizeStore.emit(this.shareCases);
2192
+ }
2193
+ onCancel(user, sharedCase) {
2194
+ this.stateService.requestCancel(sharedCase.caseId, user);
2195
+ this.synchronizeStore.emit(this.shareCases);
2196
+ }
2197
+ showNoUsersAccessInfo() {
2198
+ // A user is added to a case
2199
+ if (this.sharedCase.pendingShares) {
2200
+ if (this.sharedCase.pendingShares.length > 0) {
2201
+ return false;
2202
+ }
2148
2203
  }
2149
- else {
2150
- this.findLocationFormGroup.controls.locationSelectedFormControl.setValue(selection);
2204
+ // A case has 0 users with access to it
2205
+ if (this.sharedCase.sharedWith) {
2206
+ if (this.sharedCase.sharedWith.length === 0) {
2207
+ return true;
2208
+ }
2151
2209
  }
2152
- this.locationChanged.emit(selection);
2153
- }
2154
- search(currentValue) {
2155
- this.searchInProgress = true;
2156
- this.showAutocomplete = !!currentValue && (currentValue.length >= this.minSearchCharacters);
2157
- if (!currentValue || !currentValue.length) {
2158
- this.findLocationFormGroup.controls.locationSelectedFormControl.markAsPristine();
2159
- this.findLocationFormGroup.controls.locationSelectedFormControl.reset();
2210
+ // Access to the last user is removed
2211
+ if (this.sharedCase.sharedWith && this.sharedCase.pendingUnshares) {
2212
+ if (this.sharedCase.pendingUnshares.length > 0
2213
+ && this.sharedCase.sharedWith.length === this.sharedCase.pendingUnshares.length) {
2214
+ return true;
2215
+ }
2160
2216
  }
2161
- if (this.showAutocomplete) {
2162
- this.filter(currentValue);
2217
+ return false;
2218
+ }
2219
+ showUserHasAccessInfo() {
2220
+ return !this.showNoUsersAccessInfo();
2221
+ }
2222
+ showUserAccessTable() {
2223
+ if (this.sharedCase.pendingShares) {
2224
+ if (this.sharedCase.pendingShares.length > 0) {
2225
+ return true;
2226
+ }
2163
2227
  }
2164
- else {
2165
- this.searchInProgress = false;
2228
+ if (this.sharedCase.sharedWith) {
2229
+ if (this.sharedCase.sharedWith.length > 0) {
2230
+ return true;
2231
+ }
2166
2232
  }
2233
+ return false;
2167
2234
  }
2168
- getDisplayName(selectedLocation) {
2169
- return selectedLocation.court_name;
2235
+ combineAndSortShares(sharedWith, pendingShares) {
2236
+ return [
2237
+ ...sharedWith,
2238
+ ...pendingShares
2239
+ ].sort((user1, user2) => {
2240
+ return user1.firstName.toLowerCase() > user2.firstName.toLowerCase() ? 1 : (user2.firstName.toLowerCase() > user1.firstName.toLowerCase() ? -1 : 0);
2241
+ });
2170
2242
  }
2171
- searchLocations(term) {
2172
- return this.locationService.searchLocations(this.serviceIds, this.locationType, term);
2243
+ userIdSetter(isPending, id) {
2244
+ return isPending ? `pendingShares-${id}` : `${id}`;
2173
2245
  }
2174
- getControlCourtNameValue() {
2175
- return this.findLocationFormGroup && this.findLocationFormGroup.controls && this.findLocationFormGroup.controls.locationSelectedFormControl.value ?
2176
- this.findLocationFormGroup.controls.locationSelectedFormControl.value.court_name : '';
2246
+ buildElementId(elementName) {
2247
+ return `${elementName}-${this.sharedCase.caseId}`;
2177
2248
  }
2178
2249
  }
2179
- SearchVenueComponent.decorators = [
2250
+ SelectedCaseComponent.decorators = [
2180
2251
  { type: Component, args: [{
2181
- selector: 'xuilib-search-venue',
2182
- template: "<div class=\"auto-complete-container\">\n <div *ngIf=\"readyAfterContent\" class=\"autocomplete__wrapper\">\n <input\n [formControl]=\"findLocationFormGroup.controls.findLocationFormControl\"\n [matAutocomplete]=\"autoSearchLocation\"\n (keydown)=\"onKeyDown()\"\n (keyup)=\"onKeyUp($event)\"\n (focus)=\"onFocus()\"\n class=\"autocomplete__input autocomplete__input--default search-box\"\n [attr.disabled]=\"!disabled ? null: disabled\"\n [value]=\"getControlCourtNameValue()\"\n #inputSelectedLocation>\n <mat-autocomplete class=\"mat-autocomplete-panel-extend\" autoActiveFirstOption #autoSearchLocation=\"matAutocomplete\">\n <mat-option *ngFor=\"let location of displayedLocationsDuplicationFiltered\"\n [value]=\"getDisplayName(location)\"\n (onSelectionChange)=\"onSelectionChange(location)\"\n [ngClass]=\"{'hide-autocomplete': !showAutocomplete}\">\n {{ getDisplayName(location) }}\n </mat-option>\n <mat-option *ngIf=\"!displayedLocationsDuplicationFiltered?.length && showAutocomplete && !searchInProgress\">{{ 'No results found' }}</mat-option>\n </mat-autocomplete>\n </div>\n</div>\n",
2183
- styles: [".autocomplete__input{-webkit-appearance:none;border:2px solid #0b0c0c;border-radius:0;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;margin-bottom:0;width:100%;line-height:24px;font-size:19px;background-color:transparent;position:relative}.autocomplete__hint{color:#b1b4b6;position:absolute}.autocomplete__input--default{padding:5px}.autocomplete__input--focused{outline:3px solid #fd0;outline-offset:0;box-shadow:inset 0 0 0 2px}.autocomplete__input--show-all-values{padding:5px 34px 5px 5px;cursor:pointer}.autocomplete__dropdown-arrow-down{z-index:-1;display:inline-block;position:absolute;right:8px;width:24px;height:24px;top:10px}.autocomplete__menu{background-color:#fff;border:2px solid #0b0c0c;border-top:0;color:#0b0c0c;margin:0;max-height:342px;overflow-x:hidden;padding:0;width:100%;width:calc(100% - 4px)}.autocomplete__menu--visible{display:block}.autocomplete__menu--hidden{display:none}.autocomplete__menu--overlay{box-shadow:0 2px 6px rgba(0,0,0,.256863);left:0;position:absolute;top:100%;z-index:100}.autocomplete__menu--inline{position:relative}.autocomplete__option{border-left-width:0;border-bottom:1px solid #b1b4b6;border-right-width:0;border-top-width:1px;cursor:pointer;display:block;position:relative}.autocomplete__option>*{pointer-events:none}.autocomplete__option:first-of-type{border-top-width:0}.autocomplete__option:last-of-type{border-bottom-width:0}.autocomplete__option--odd{background-color:#fafafa}.autocomplete__option--focused,.autocomplete__option:hover{background-color:#1d70b8;border-color:#1d70b8;color:#fff;outline:0}.autocomplete__option--no-results{background-color:#fafafa;color:#646b6f;cursor:not-allowed}.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.25}.autocomplete__hint,.autocomplete__option{padding:5px}@media (min-width:641px){.autocomplete__hint,.autocomplete__input,.autocomplete__option{font-size:13px;line-height:1.31579}}.div-action{display:inline-block}.add-location{display:inline}.remove-location-button{margin:5px}.hide-autocomplete{display:none}.auto-complete-container{min-width:550px;display:inline-block;margin-right:4px}"]
2252
+ selector: 'xuilib-selected-case',
2253
+ template: "<div id=\"{{buildElementId('govuk-accordion__section')}}\" class=\"govuk-accordion__section\">\n <div class=\"govuk-grid-row govuk-case-header\">\n <div class=\"govuk-grid-column-three-quarters\">\n <h3 id=\"{{buildElementId('case-title')}}\" class=\"govuk-case-title\">{{ sharedCase.caseTitle }}</h3>\n <h1 id=\"{{buildElementId('case-id')}}\" class=\"govuk-case-sub-title\">{{ sharedCase.caseId }}</h1>\n </div>\n <div class=\"govuk-grid-column-twenty-percent\">\n <button id=\"{{buildElementId('btn-deselect-case')}}\" class=\"govuk-button hmcts-button--secondary\" (click)=\"onDeselect(sharedCase)\" title=\"Deselect case\">Deselect case</button>\n </div>\n <div class=\"govuk-accordion__section-header govuk-grid-column-five-percent\">\n <div class=\"govuk-accordion__section-heading\">\n <button type=\"button\" id=\"{{buildElementId('accordion-with-summary-sections-heading')}}\"\n aria-controls=\"accordion-with-summary-sections-content-1\" class=\"govuk-accordion__section-button\"\n aria-describedby=\"accordion-with-summary-sections-summary-1\" aria-expanded=\"false\" title=\"Expand or Collapse\">\n <span class=\"govuk-accordion__icon\" aria-hidden=\"true\"></span></button>\n </div>\n </div>\n </div>\n <div id=\"{{buildElementId('accordion-with-summary-sections-content')}}\" class=\"govuk-accordion__section-content\"\n aria-labelledby=\"buildElementId('accordion-with-summary-sections-heading')\" >\n <div class=\"govuk-grid-row\" *ngIf=\"showNoUsersAccessInfo()\">\n <span id=\"{{buildElementId('access-info-no-user')}}\" class=\"govuk-div-align-left\">No users from your organisation currently have access to this case.</span>\n </div>\n <div class=\"govuk-grid-row\" *ngIf=\"showUserHasAccessInfo()\">\n <span id=\"{{buildElementId('access-info-has-users')}}\" class=\"govuk-div-align-left\">Users from your organisation with access to this case.</span>\n </div>\n <table class=\"govuk-table\" *ngIf=\"showUserAccessTable()\">\n <thead class=\"govuk-table__head\">\n <tr class=\"govuk-table__row\">\n <th id=\"{{buildElementId('name-heading')}}\" class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Name</th>\n <th id=\"{{buildElementId('email-heading')}}\" class=\"govuk-table__header govuk-table-column-header\" scope=\"col\">Email address</th>\n <th id=\"{{buildElementId('action-heading')}}\" class=\"govuk-table__header govuk-table-column-actions\" scope=\"col\">Actions</th>\n <th id=\"{{buildElementId('label-heading')}}\" class=\"govuk-table__header govuk-table-column-label\" scope=\"col\">&nbsp;&nbsp;</th>\n </tr>\n </thead>\n <tbody class=\"govuk-table__body\">\n <tr class=\"govuk-table__row\" *ngFor=\"let user of combinedSortedShares; index as idx; trackBy: trackByUserId\">\n <td id=\"user-full-name-{{ userIdSetter(canCancel(sharedCase.caseId, user) | async, idx) }}\" class=\"govuk-table__cell\">{{ user.firstName + ' ' + user.lastName }}</td>\n <td id=\"user-email-{{ userIdSetter(canCancel(sharedCase.caseId, user) | async, idx) }}\" class=\"govuk-table__cell\">{{ user.email }}</td>\n <td class=\"govuk-table__cell\">\n <a *ngIf=\"canRemove(sharedCase.caseId, user) | async\" (click)=\"onRemove(user, sharedCase)\" href=\"javascript:void(0);\">Remove <span class=\"govuk-visually-hidden\">{{ user.firstName + ' ' + user.lastName }} from case</span></a>\n <a *ngIf=\"canCancel(sharedCase.caseId, user) | async\" (click)=\"onCancel(user, sharedCase)\" href=\"javascript:void(0);\">Cancel <span class=\"govuk-visually-hidden\">adding {{ user.firstName + ' ' + user.lastName }} to case</span></a>\n </td>\n <td class=\"govuk-table__cell\">\n <span *ngIf=\"isToBeRemoved(sharedCase.caseId, user) | async\" class=\"hmcts-badge hmcts-badge--red\">To be removed</span>\n <span *ngIf=\"isToBeAdded(sharedCase.caseId, user) | async\" class=\"hmcts-badge\">To be added</span>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n",
2254
+ styles: [".govuk-case-header{border-top:1px solid #bfc1c3}.govuk-case-title{font-size:24px;color:#005ea5;font-weight:700}.govuk-case-sub-title,.govuk-case-title{font-family:nta,Arial,sans-serif;padding-left:0}.govuk-case-sub-title{font-size:1rem!important;color:#6f777b;font-weight:400}.govuk-grid-row{margin-left:0;margin-right:0}.govuk-grid-column-three-quarters{padding-top:5px;padding-left:0}.govuk-grid-column-twenty-percent{box-sizing:border-box;padding-top:10px;width:20%;float:left}.govuk-grid-column-five-percent{box-sizing:border-box;padding-top:15px;width:5%;float:left}.govuk-table-column-header{width:40%}.govuk-table-column-actions,.govuk-table-column-label{width:10%}.govuk-div-align-left{font-family:nta,Arial,sans-serif;font-size:1.1875rem!important;line-height:1.31579!important;text-align:left;margin-bottom:20px;padding-left:0;color:#0b0c0c}.govuk-accordion__section-header{border-top:0}.govuk-accordion__section-content{padding-top:0}"]
2184
2255
  },] }
2185
2256
  ];
2186
- SearchVenueComponent.ctorParameters = () => [
2187
- { type: LocationService },
2188
- { type: FormBuilder }
2257
+ SelectedCaseComponent.ctorParameters = () => [
2258
+ { type: CaseSharingStateService }
2189
2259
  ];
2190
- SearchVenueComponent.propDecorators = {
2191
- control: [{ type: Input }],
2192
- disabled: [{ type: Input }],
2193
- locationType: [{ type: Input }],
2194
- selectedLocations: [{ type: Input }],
2195
- serviceIds: [{ type: Input }],
2196
- submitted: [{ type: Input }],
2197
- autoCompleteInputBox: [{ type: ViewChild, args: ['inputSelectedLocation', { read: ElementRef },] }],
2198
- showAutocomplete: [{ type: Input }],
2199
- displayedLocations: [{ type: Input }],
2200
- locationChanged: [{ type: Output }]
2260
+ SelectedCaseComponent.propDecorators = {
2261
+ sharedCase: [{ type: Input }],
2262
+ selectedUser: [{ type: Input }],
2263
+ opened: [{ type: Input }],
2264
+ removeUserFromCaseToggleOn: [{ type: Input }],
2265
+ unselect: [{ type: Output }],
2266
+ synchronizeStore: [{ type: Output }]
2201
2267
  };
2202
2268
 
2203
- const getAllCaseworkersFromServices = (caseworkersByService) => {
2204
- let allCaseworkers = [];
2205
- caseworkersByService.forEach(caseworkerListByService => {
2206
- allCaseworkers = allCaseworkers.concat(caseworkerListByService.caseworkers);
2207
- });
2208
- return allCaseworkers;
2209
- };
2210
- const getSessionStorageKeyForServiceId = (serviceId) => {
2211
- return `${serviceId}-caseworkers`;
2212
- };
2213
- const getCaseworkers = (serviceId, sessionStorageService) => {
2214
- const sessionKey = getSessionStorageKeyForServiceId(serviceId);
2215
- const value = sessionStorageService.getItem(sessionKey);
2216
- if (value) {
2217
- return JSON.parse(value);
2269
+ class ServiceMessageComponent {
2270
+ constructor() {
2271
+ this.hideMessage = new EventEmitter();
2272
+ }
2273
+ onHideMessageEvent(key) {
2274
+ this.hideMessage.emit(key);
2218
2275
  }
2219
- };
2220
- const setCaseworkers = (serviceId, caseworkers, sessionStorageService) => {
2221
- const sessionKey = getSessionStorageKeyForServiceId(serviceId);
2222
- sessionStorageService.setItem(sessionKey, JSON.stringify(caseworkers));
2223
- };
2224
-
2225
- var BadgeColour;
2226
- (function (BadgeColour) {
2227
- BadgeColour["BADGE_RED"] = "hmcts-badge--red";
2228
- BadgeColour["BADGE_BLUE"] = "hmcts-badge--blue";
2229
- BadgeColour["BADGE_GREEN"] = "hmcts-badge--green";
2230
- })(BadgeColour || (BadgeColour = {}));
2231
-
2232
- class AnonymousFeatureUser {
2233
- }
2234
- class LoggedInFeatureUser {
2235
- }
2236
-
2237
- var PersonRole;
2238
- (function (PersonRole) {
2239
- PersonRole["JUDICIAL"] = "Judicial";
2240
- PersonRole["CASEWORKER"] = "Legal Ops";
2241
- PersonRole["ADMIN"] = "Admin";
2242
- PersonRole["ALL"] = "All";
2243
- })(PersonRole || (PersonRole = {}));
2244
- // Note: RoleCategory could replace PersonRole possibly
2245
- // However a lot of webapp logic is based on current PersonRole understanding
2246
- var RoleCategory;
2247
- (function (RoleCategory) {
2248
- RoleCategory["JUDICIAL"] = "JUDICIAL";
2249
- RoleCategory["CASEWORKER"] = "LEGAL_OPERATIONS";
2250
- RoleCategory["ADMIN"] = "ADMIN";
2251
- RoleCategory["ALL"] = "ALL";
2252
- })(RoleCategory || (RoleCategory = {}));
2253
-
2254
- class RadioFilterFieldConfig {
2255
2276
  }
2277
+ ServiceMessageComponent.decorators = [
2278
+ { type: Component, args: [{
2279
+ selector: 'xuilib-service-message',
2280
+ template: "<div class=\"hmcts-banner hmcts-banner--warning\">\n\n <svg class=\"hmcts-banner__icon\" fill=\"currentColor\" role=\"presentation\" focusable=\"false\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 25 25\" height=\"25\" width=\"25\">\n <path d=\"M13.6,15.4h-2.3v-4.5h2.3V15.4z M13.6,19.8h-2.3v-2.2h2.3V19.8z M0,23.2h25L12.5,2L0,23.2z\" />\n </svg>\n\n <div class=\"hmcts-banner__message\">\n <span class=\"hmcts-banner__assistive\">Warning</span>\n <h2 class=\"govuk-heading-s\" [innerHTML]=\"message\"></h2>\n <a [routerLink]=\"\" class=\"govuk-link--no-visited-state\" (click)=\"onHideMessageEvent(key)\">Hide message</a>\n </div>\n\n</div>"
2281
+ },] }
2282
+ ];
2283
+ ServiceMessageComponent.ctorParameters = () => [];
2284
+ ServiceMessageComponent.propDecorators = {
2285
+ message: [{ type: Input }],
2286
+ key: [{ type: Input }],
2287
+ hideMessage: [{ type: Output }]
2288
+ };
2256
2289
 
2257
- class SessionStorageService {
2258
- /**
2259
- * Get an item from the session storage.
2260
- * If remove is true, the item will be removed once read
2261
- * @param removeAfterRead removed the key once it has been read
2262
- */
2263
- getItem(key, removeAfterRead = false) {
2264
- const item = sessionStorage.getItem(key);
2265
- if (removeAfterRead) {
2266
- this.removeItem(key);
2267
- }
2268
- return item;
2290
+ class FeatureToggleService {
2291
+ // tslint:disable-next-line: variable-name
2292
+ initialize(_user, _clientId) {
2293
+ throw new Error('Not implemented');
2269
2294
  }
2270
- /**
2271
- * Set an item in the session storage.
2272
- */
2273
- setItem(key, value) {
2274
- sessionStorage.setItem(key, value);
2295
+ // tslint:disable-next-line: variable-name
2296
+ isEnabled(_feature) {
2297
+ throw new Error('Not implemented');
2275
2298
  }
2276
- /**
2277
- * Remove an item in the session storage.
2278
- */
2279
- removeItem(key) {
2280
- sessionStorage.removeItem(key);
2299
+ // tslint:disable-next-line: variable-name
2300
+ getValue(_key, _defaultValue) {
2301
+ throw new Error('Not implemented');
2281
2302
  }
2282
- /**
2283
- * Clear all the items held in session storage.
2284
- */
2285
- clear() {
2286
- sessionStorage.clear();
2303
+ // tslint:disable-next-line: variable-name
2304
+ getValueOnce(_key, _defaultValue) {
2305
+ throw new Error('Not implemented');
2287
2306
  }
2288
2307
  }
2289
- SessionStorageService.ɵprov = i0.ɵɵdefineInjectable({ factory: function SessionStorageService_Factory() { return new SessionStorageService(); }, token: SessionStorageService, providedIn: "root" });
2290
- SessionStorageService.decorators = [
2308
+ FeatureToggleService.ɵprov = i0.ɵɵdefineInjectable({ factory: function FeatureToggleService_Factory() { return new FeatureToggleService(); }, token: FeatureToggleService, providedIn: "root" });
2309
+ FeatureToggleService.decorators = [
2291
2310
  { type: Injectable, args: [{
2292
2311
  providedIn: 'root'
2293
2312
  },] }
2294
2313
  ];
2295
2314
 
2296
- class FindAPersonService {
2297
- constructor(http, sessionStorageService) {
2298
- this.http = http;
2299
- this.sessionStorageService = sessionStorageService;
2315
+ class ServiceMessagesComponent {
2316
+ constructor(featureToggleService) {
2317
+ this.featureToggleService = featureToggleService;
2318
+ this.filteredMessages = new Map();
2300
2319
  }
2301
- find(searchOptions) {
2302
- const userInfoStr = this.sessionStorageService.getItem('userDetails');
2303
- if (userInfoStr && !searchOptions.userIncluded) {
2304
- const userInfo = JSON.parse(userInfoStr);
2305
- this.userId = userInfo.id ? userInfo.id : userInfo.uid;
2306
- }
2307
- this.assignedUser = searchOptions.assignedUser ? searchOptions.assignedUser : null;
2308
- return this.http.post('/workallocation2/findPerson', { searchOptions })
2309
- .pipe(map(judiciary => judiciary.filter(judge => !([this.assignedUser, this.userId].includes(judge.id)))));
2320
+ ngOnInit() {
2321
+ this.getServiceMessages();
2310
2322
  }
2311
- findCaseworkers(searchOptions) {
2312
- const userInfoStr = this.sessionStorageService.getItem('userDetails');
2313
- if (userInfoStr) {
2314
- const userInfo = JSON.parse(userInfoStr);
2315
- this.userId = userInfo.id ? userInfo.id : userInfo.uid;
2316
- }
2317
- this.assignedUser = searchOptions.assignedUser ? searchOptions.assignedUser : null;
2318
- const fullServices = searchOptions.services;
2319
- const storedServices = [];
2320
- const newServices = [];
2321
- const storedCaseworkersByService = [];
2322
- fullServices.forEach(serviceId => {
2323
- const serviceKey = getSessionStorageKeyForServiceId(serviceId);
2324
- if (this.sessionStorageService.getItem(serviceKey)) {
2325
- storedServices.push(serviceId);
2326
- storedCaseworkersByService.push({ service: serviceId, caseworkers: JSON.parse(this.sessionStorageService.getItem(serviceKey)) });
2327
- }
2328
- else {
2329
- newServices.push(serviceId);
2323
+ getServiceMessages() {
2324
+ this.featureToggleService.getValue(this.featureToggleKey, null)
2325
+ .subscribe(messages => {
2326
+ if (!!messages) {
2327
+ this.createFilteredMessages(messages);
2330
2328
  }
2331
2329
  });
2332
- // if all services are stored then return the stored caseworkers by service
2333
- if (storedServices.length === fullServices.length) {
2334
- const storedCaseworkers = getAllCaseworkersFromServices(storedCaseworkersByService);
2335
- return of(this.searchInCaseworkers(storedCaseworkers, searchOptions));
2336
- }
2337
- // all serviceIds passed in as node layer getting used anyway and caseworkers also stored there
2338
- return this.http.post('/workallocation2/retrieveCaseWorkersForServices', { fullServices }).pipe(tap(caseworkersByService => {
2339
- caseworkersByService.forEach(caseworkerListByService => {
2340
- // for any new service, ensure that they are then stored in the session
2341
- if (newServices.includes(caseworkerListByService.service)) {
2342
- setCaseworkers(caseworkerListByService.service, caseworkerListByService.caseworkers, this.sessionStorageService);
2343
- }
2344
- });
2345
- }), map(caseworkersByService => {
2346
- const givenCaseworkers = getAllCaseworkersFromServices(caseworkersByService);
2347
- return this.searchInCaseworkers(givenCaseworkers, searchOptions);
2348
- }));
2349
2330
  }
2350
- mapCaseworkers(caseworkers, roleCategory) {
2351
- const people = [];
2352
- caseworkers.forEach((caseworker) => {
2353
- const thisPerson = {
2354
- email: caseworker.email,
2355
- name: `${caseworker.firstName} ${caseworker.lastName}`,
2356
- id: caseworker.idamId,
2357
- domain: caseworker.roleCategory === RoleCategory.CASEWORKER ? PersonRole.CASEWORKER : PersonRole.ADMIN,
2358
- };
2359
- if (caseworker.roleCategory === roleCategory || roleCategory === RoleCategory.ALL) {
2360
- people.push(thisPerson);
2331
+ createFilteredMessages(messages) {
2332
+ this.hiddenBanners = JSON.parse(window.sessionStorage.getItem(this.serviceMessageCookie)) || [];
2333
+ Object.keys(messages).forEach(key => {
2334
+ const regEx = new RegExp(key);
2335
+ if (this.userRoles.some(e => regEx.test(e)) && this.hiddenBanners.indexOf(key) === -1) {
2336
+ this.filteredMessages.set(key, messages[key]);
2361
2337
  }
2362
2338
  });
2363
- return people;
2364
2339
  }
2365
- searchInCaseworkers(caseworkers, searchOptions) {
2366
- let roleCategory = RoleCategory.ALL;
2367
- if (!(searchOptions.userRole === PersonRole.ALL)) {
2368
- roleCategory = searchOptions.userRole === PersonRole.CASEWORKER ? RoleCategory.CASEWORKER : RoleCategory.ADMIN;
2340
+ hideMessage(key) {
2341
+ this.filteredMessages.delete(key);
2342
+ this.hiddenBanners.push(key);
2343
+ window.sessionStorage.setItem(this.serviceMessageCookie, JSON.stringify(this.hiddenBanners));
2344
+ }
2345
+ }
2346
+ ServiceMessagesComponent.decorators = [
2347
+ { type: Component, args: [{
2348
+ selector: 'xuilib-service-messages',
2349
+ template: "<div *ngIf=\"filteredMessages?.size > 0\" class=\"govuk-width-container govuk-!-margin-top-6\">\n <xuilib-service-message *ngFor=\"let message of filteredMessages | keyvalue\" [key]=\"message.key\"\n [message]=\"message.value\" (hideMessage)=\"hideMessage($event)\"></xuilib-service-message>\n</div>"
2350
+ },] }
2351
+ ];
2352
+ ServiceMessagesComponent.ctorParameters = () => [
2353
+ { type: FeatureToggleService }
2354
+ ];
2355
+ ServiceMessagesComponent.propDecorators = {
2356
+ userRoles: [{ type: Input }],
2357
+ featureToggleKey: [{ type: Input }],
2358
+ serviceMessageCookie: [{ type: Input }]
2359
+ };
2360
+
2361
+ class ShareCaseConfirmComponent {
2362
+ constructor(stateService) {
2363
+ this.stateService = stateService;
2364
+ this.shareCases = []; // cases selected for sharing
2365
+ this.changeLink = '';
2366
+ this.completeLink = '';
2367
+ }
2368
+ ngOnInit() {
2369
+ this.shareCases$.subscribe(shareCases => {
2370
+ this.shareCases = shareCases;
2371
+ this.stateService.setCases(shareCases);
2372
+ });
2373
+ this.shareCases$ = this.stateService.state;
2374
+ }
2375
+ }
2376
+ ShareCaseConfirmComponent.decorators = [
2377
+ { type: Component, args: [{
2378
+ selector: 'xuilib-share-case-confirm',
2379
+ template: "<div id=\"casesToConfirm\">\n <h3 class=\"govuk-heading-l\">Cases</h3>\n <div *ngIf=\"shareCases && shareCases.length > 0\" id=\"summarySections\">\n <xuilib-selected-case-list\n [shareCases$]=\"shareCases$\"\n [toConfirm]=\"true\"\n [changeLink]=\"changeLink\">\n </xuilib-selected-case-list>\n </div>\n\n <div id=\"noCaseDisplay\" *ngIf=\"shareCases && shareCases.length === 0\" class=\"govuk-hint\">\n No cases to display.\n </div>\n\n</div>\n\n<div id=\"share-case-nav\" *ngIf=\"shareCases && shareCases.length > 0\">\n <button class=\"govuk-button\" title=\"Confirm\" [routerLink]=\"completeLink\">Confirm</button>\n</div>\n",
2380
+ styles: [""]
2381
+ },] }
2382
+ ];
2383
+ ShareCaseConfirmComponent.ctorParameters = () => [
2384
+ { type: CaseSharingStateService }
2385
+ ];
2386
+ ShareCaseConfirmComponent.propDecorators = {
2387
+ shareCases$: [{ type: Input }],
2388
+ changeLink: [{ type: Input }],
2389
+ completeLink: [{ type: Input }]
2390
+ };
2391
+
2392
+ class UserSelectComponent {
2393
+ constructor() {
2394
+ this.selected = new EventEmitter();
2395
+ this.control = new FormControl();
2396
+ }
2397
+ ngOnInit() {
2398
+ this.filteredUsers = this.control.valueChanges.pipe(map(value => typeof value === typeof 'string' ? this.filterUsers(value) : this.users));
2399
+ this.selected.emit(null);
2400
+ }
2401
+ displayValue(user) {
2402
+ return user ? `${user.firstName} ${user.lastName} - ${user.email}` : '';
2403
+ }
2404
+ onSelected(e) {
2405
+ this.selected.emit(e.option.value);
2406
+ }
2407
+ clear() {
2408
+ this.control.setValue(null);
2409
+ }
2410
+ onUserChange(newUserValue) {
2411
+ if (!newUserValue || !newUserValue.email) {
2412
+ this.selected.emit(null);
2369
2413
  }
2370
- const searchTerm = searchOptions && searchOptions.searchTerm ? searchOptions.searchTerm.toLowerCase() : '';
2371
- const people = caseworkers ? this.mapCaseworkers(caseworkers, roleCategory) : [];
2372
- const finalPeopleList = people.filter(person => person && person.name && person.name.toLowerCase().includes(searchTerm));
2373
- return searchOptions.userIncluded ? finalPeopleList.filter(person => person && person.id !== this.assignedUser)
2374
- : finalPeopleList.filter(person => person && person.id !== this.userId && person.id !== this.assignedUser);
2375
2414
  }
2376
- searchJudicial(value, serviceId) {
2377
- return this.http.post('api/prd/judicial/getJudicialUsersSearch', { searchString: value, serviceCode: serviceId });
2415
+ filterUsers(value) {
2416
+ if (value) {
2417
+ value = value.toLowerCase();
2418
+ return this.users.filter(user => {
2419
+ if (user.firstName.toLowerCase().includes(value)) {
2420
+ return true;
2421
+ }
2422
+ if (user.lastName.toLowerCase().includes(value)) {
2423
+ return true;
2424
+ }
2425
+ if (user.email.toLowerCase().includes(value)) {
2426
+ return true;
2427
+ }
2428
+ return false;
2429
+ });
2430
+ }
2431
+ return [];
2378
2432
  }
2379
2433
  }
2380
- FindAPersonService.caseworkersKey = 'caseworkers';
2381
- FindAPersonService.ɵprov = i0.ɵɵdefineInjectable({ factory: function FindAPersonService_Factory() { return new FindAPersonService(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(SessionStorageService)); }, token: FindAPersonService, providedIn: "root" });
2382
- FindAPersonService.decorators = [
2383
- { type: Injectable, args: [{
2384
- providedIn: 'root'
2434
+ UserSelectComponent.decorators = [
2435
+ { type: Component, args: [{
2436
+ selector: 'xuilib-user-select',
2437
+ template: "<input class=\"govuk-input\" type=\"text\" [matAutocomplete]=\"dropdown\" [formControl]=\"control\" (ngModelChange)=\"onUserChange($event)\" aria-labelledby=\"add-user-hint\">\n\n<mat-autocomplete #dropdown=\"matAutocomplete\" [displayWith]=\"displayValue\" autoActiveFirstOption (optionSelected)=\"onSelected($event)\">\n <mat-option *ngFor=\"let user of filteredUsers | async\" [value]=\"user\">\n {{ user.firstName }} {{ user.lastName }} - {{ user.email }}\n </mat-option>\n</mat-autocomplete>",
2438
+ styles: [""]
2385
2439
  },] }
2386
2440
  ];
2387
- FindAPersonService.ctorParameters = () => [
2388
- { type: HttpClient },
2389
- { type: SessionStorageService }
2390
- ];
2441
+ UserSelectComponent.ctorParameters = () => [];
2442
+ UserSelectComponent.propDecorators = {
2443
+ users: [{ type: Input }],
2444
+ selected: [{ type: Output }]
2445
+ };
2391
2446
 
2392
- class SearchJudicialsComponent {
2393
- constructor(judicialService, fb) {
2394
- this.judicialService = judicialService;
2395
- this.disabled = null;
2396
- this.selectedJudicials = [];
2397
- this.submitted = true;
2398
- this.placeholderContent = '';
2399
- this.showAutocomplete = false;
2400
- this.judicialChanged = new EventEmitter();
2401
- this.idValue = '';
2402
- this.errorMessage = 'You must select a name';
2403
- this.serviceId = '';
2404
- this.minSearchCharacters = 3;
2405
- this.keyUpSubject$ = new Subject();
2406
- this.searchInProgress = false;
2407
- this.formGroup = fb.group({
2408
- formControl: [null],
2409
- selectedFormControl: [null]
2410
- });
2447
+ class ShareCaseComponent {
2448
+ constructor(stateService) {
2449
+ this.stateService = stateService;
2450
+ this.shareCases = []; // cases selected for sharing
2451
+ this.removeUserFromCaseToggleOn = false;
2452
+ this.users = []; // users of this organisation the cases can be shared with
2453
+ this.confirmLink = '';
2454
+ this.unselect = new EventEmitter();
2455
+ this.synchronizeStore = new EventEmitter();
2411
2456
  }
2412
2457
  ngOnInit() {
2413
- this.displayedJudicials = [];
2414
- if (this.control) {
2415
- if (this.formGroup && this.formGroup.controls) {
2416
- this.formGroup.controls.selectedFormControl = this.control;
2417
- this.formGroup.controls.formControl.setValue(this.getControlValueDisplayText());
2418
- }
2419
- }
2420
- this.keyUpSubject$.pipe(debounceTime(500)).subscribe(searchValue => this.search(searchValue));
2458
+ this.shareCases$.subscribe(shareCases => {
2459
+ this.shareCases = shareCases;
2460
+ this.stateService.setCases(shareCases);
2461
+ });
2462
+ this.shareCases$ = this.stateService.state;
2421
2463
  }
2422
- onKeyDown() {
2423
- this.judicialChanged.emit();
2464
+ onUnselect(c) {
2465
+ this.unselect.emit(c);
2466
+ this.stateService.removeCase(c.caseId);
2424
2467
  }
2425
- onKeyUp(event) {
2426
- this.showAutocomplete = false;
2427
- this.keyUpSubject$.next(event.target.value);
2468
+ onSynchronizeStore(event) {
2469
+ this.synchronizeStore.emit(event);
2428
2470
  }
2429
- onFocus() {
2430
- this.showAutocomplete = false;
2471
+ onSelectedUser(user) {
2472
+ this.selectedUser = user;
2431
2473
  }
2432
- get displayedJudicialsDuplicationFiltered() {
2433
- return this.displayedJudicials.filter(judicial => !this.selectedJudicials.map(selectedJudicial => selectedJudicial.idamId).includes(judicial.idamId));
2474
+ addUser() {
2475
+ const newSharedCases = this.stateService.requestShare(this.selectedUser);
2476
+ this.selectedUser = null;
2477
+ if (this.userSelect) {
2478
+ this.userSelect.clear();
2479
+ }
2480
+ this.synchronizeStore.emit(newSharedCases);
2434
2481
  }
2435
- filter(term) {
2436
- this.searchJudicials(term, this.serviceId).pipe(mergeMap((apiData) => {
2437
- const apiFilter = apiData.filter(apiJudicial => !this.selectedJudicials.map(selectedJudicial => selectedJudicial.idamId).includes(apiJudicial.idamId));
2438
- this.displayedJudicials = apiFilter;
2439
- this.searchInProgress = false;
2440
- return apiFilter;
2441
- })).subscribe(judicial => {
2442
- if (term === judicial.knownAs) {
2443
- this.formGroup.controls.selectedFormControl.setValue(judicial);
2444
- this.displayedJudicials = [];
2445
- this.judicialChanged.emit(judicial);
2446
- this.showAutocomplete = false;
2482
+ isDisabledAdd() {
2483
+ return this.selectedUser === null || this.shareCases.length === 0;
2484
+ }
2485
+ isDisabledContinue() {
2486
+ let isDisabled = true;
2487
+ this.shareCases$.subscribe(shareCases => {
2488
+ for (const caseState of shareCases) {
2489
+ if (caseState.pendingShares && caseState.pendingShares.length > 0) {
2490
+ isDisabled = false;
2491
+ break;
2492
+ }
2493
+ if (caseState.pendingUnshares && caseState.pendingUnshares.length > 0) {
2494
+ isDisabled = false;
2495
+ break;
2496
+ }
2447
2497
  }
2448
- this.searchInProgress = false;
2449
2498
  });
2499
+ return isDisabled;
2450
2500
  }
2451
- onSelectionChange(selection) {
2452
- if (this.formGroup.controls.formControl instanceof FormArray) {
2453
- this.formGroup.controls.selectedFormControl.push(new FormControl(selection.idamId));
2454
- }
2455
- else {
2456
- this.formGroup.controls.selectedFormControl.setValue(selection);
2501
+ onDeselect(sharedCase) {
2502
+ if (sharedCase !== null) {
2503
+ const updated = [];
2504
+ for (const element of this.shareCases) {
2505
+ if (element.caseId !== sharedCase.caseId) {
2506
+ updated.push(element);
2507
+ }
2508
+ }
2509
+ this.shareCases = updated;
2457
2510
  }
2458
- this.judicialChanged.emit(selection);
2511
+ this.stateService.setCases(this.shareCases);
2459
2512
  }
2460
- search(currentValue) {
2461
- this.searchInProgress = true;
2462
- this.showAutocomplete = !!currentValue && (currentValue.length >= this.minSearchCharacters);
2463
- if (!!currentValue) {
2464
- this.formGroup.controls.selectedFormControl.markAsDirty();
2465
- }
2466
- else {
2467
- this.formGroup.controls.selectedFormControl.reset();
2468
- }
2469
- if (this.showAutocomplete) {
2470
- this.filter(currentValue);
2471
- }
2472
- else {
2473
- this.searchInProgress = false;
2474
- }
2513
+ }
2514
+ ShareCaseComponent.decorators = [
2515
+ { type: Component, args: [{
2516
+ selector: 'xuilib-share-case',
2517
+ template: "<div id=\"add-user\">\n <label class=\"govuk-label govuk-!-font-weight-bold\" for=\"add-user-input\">Enter email address</label>\n <span id=\"add-user-hint\" class=\"govuk-hint\">\n Search by name or email address. You can only add people from your organisation individually - but you can add as many as you like.\n </span>\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-two-thirds\">\n <xuilib-user-select\n id=\"add-user-input\"\n aria-describedby=\"add-user-hint\"\n [users]=\"users\"\n (selected)=\"onSelectedUser($event)\">\n </xuilib-user-select>\n </div>\n <div class=\"govuk-grid-column-one-thirds\">\n <button id=\"btn-add-user\" (click)=\"addUser()\" class=\"govuk-button\" [disabled]=\"isDisabledAdd()\" title=\"Add user to the case\">Add</button>\n </div>\n </div>\n <details id=\"add-user-help\" class=\"govuk-details\" data-module=\"govuk-details\">\n <summary class=\"govuk-details__summary\">\n <span id=\"content-why-can-not-find-email\" class=\"govuk-details__summary-text\">\n Can\u2019t find an email address?\n </span>\n </summary>\n <div id=\"content-reason-can-not-find-email\" class=\"govuk-details__text\">\n If you can\u2019t find your colleague\u2019s email address, they will need to complete their registration. Contact your\n administrator for help.\n </div>\n </details>\n</div>\n\n<div id=\"cases\">\n <h3 id=\"title-selected-cases\" class=\"govuk-heading-m\">Selected cases</h3>\n <div *ngIf=\"shareCases && shareCases.length > 0\" class=\"govuk-accordion\" data-module=\"govuk-accordion\" id=\"accordion-with-summary-sections\">\n <xuilib-selected-case-list\n [shareCases$]=\"shareCases$\"\n [removeUserFromCaseToggleOn]=\"removeUserFromCaseToggleOn\"\n (unselect)=\"onUnselect($event)\"\n (synchronizeStore)=\"onSynchronizeStore($event)\"\n >\n </xuilib-selected-case-list>\n </div>\n\n <div id=\"noCaseDisplay\" *ngIf=\"shareCases && shareCases.length === 0\" class=\"govuk-hint\">\n No cases to display.\n </div>\n\n</div>\n\n<div id=\"share-case-nav\">\n <button class=\"govuk-button\" [disabled]=\"isDisabledContinue()\" title=\"Continue\" [routerLink]=\"confirmLink\">Continue</button>\n</div>\n",
2518
+ styles: [""]
2519
+ },] }
2520
+ ];
2521
+ ShareCaseComponent.ctorParameters = () => [
2522
+ { type: CaseSharingStateService }
2523
+ ];
2524
+ ShareCaseComponent.propDecorators = {
2525
+ removeUserFromCaseToggleOn: [{ type: Input }],
2526
+ shareCases$: [{ type: Input }],
2527
+ users: [{ type: Input }],
2528
+ confirmLink: [{ type: Input }],
2529
+ unselect: [{ type: Output }],
2530
+ synchronizeStore: [{ type: Output }],
2531
+ userSelect: [{ type: ViewChild, args: [UserSelectComponent, { static: true },] }]
2532
+ };
2533
+
2534
+ class TabComponent {
2535
+ constructor() {
2536
+ this.tabChange = new EventEmitter();
2475
2537
  }
2476
- getDisplayName(selectedJudicial) {
2477
- return `${selectedJudicial.knownAs} (${selectedJudicial.emailId})`;
2538
+ tabChanged(event) {
2539
+ this.tabChange.emit(event);
2478
2540
  }
2479
- searchJudicials(term, serviceId) {
2480
- return this.judicialService.searchJudicial(term, serviceId);
2541
+ }
2542
+ TabComponent.decorators = [
2543
+ { type: Component, args: [{
2544
+ selector: 'xuilib-tab',
2545
+ template: "<mat-tab-group animationDuration=\"0ms\" (selectedTabChange)=\"tabChanged($event)\">\n <mat-tab *ngFor=\"let tabItem of tabItems; let last = last;\" [label]=\"tabItem.text\">\n </mat-tab>\n</mat-tab-group>"
2546
+ },] }
2547
+ ];
2548
+ TabComponent.ctorParameters = () => [];
2549
+ TabComponent.propDecorators = {
2550
+ tabItems: [{ type: Input }],
2551
+ tabChange: [{ type: Output }]
2552
+ };
2553
+
2554
+ class TcConfirmComponent {
2555
+ constructor() {
2556
+ this.confirm = new EventEmitter();
2481
2557
  }
2482
- getControlValueDisplayText() {
2483
- return this.formGroup && this.formGroup.controls && this.formGroup.controls.selectedFormControl.value ?
2484
- this.getDisplayName(this.formGroup.controls.selectedFormControl.value) : '';
2558
+ onClick() {
2559
+ this.confirm.emit();
2485
2560
  }
2486
2561
  }
2487
- SearchJudicialsComponent.decorators = [
2562
+ TcConfirmComponent.decorators = [
2563
+ { type: Component, args: [{
2564
+ selector: 'xuilib-tc-confirm',
2565
+ template: "<div class=\"govuk-width-container\">\n <main role=\"main\" class=\"govuk-main-wrapper\">\n <div class=\"govuk-grid-row\">\n <div class=\"govuk-grid-column-two-thirds\">\n <div class=\"column-two-thirds\">\n <h1 class=\"govuk-heading-xl\">Using this service</h1>\n <h2 class=\"govuk-heading-m\">Terms and conditions</h2>\n <p>We've recently updated the\n <a\n routerLink=\"/terms-and-conditions\"\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n >terms and conditions</a\n >.\n </p>\n <p>You must review and accept them.\n </p>\n <p>\n <button class=\"govuk-button\" (click)=\"onClick()\">\n {{ buttonText }}\n </button>\n </p>\n </div>\n </div>\n </div>\n <div class=\"govuk-grid-column-one-third\"></div>\n </main>\n</div>\n",
2566
+ styles: [""]
2567
+ },] }
2568
+ ];
2569
+ TcConfirmComponent.ctorParameters = () => [];
2570
+ TcConfirmComponent.propDecorators = {
2571
+ buttonText: [{ type: Input }],
2572
+ confirm: [{ type: Output }]
2573
+ };
2574
+
2575
+ class TcDisplayHtmlComponent {
2576
+ constructor() { }
2577
+ }
2578
+ TcDisplayHtmlComponent.decorators = [
2579
+ { type: Component, args: [{
2580
+ selector: 'xuilib-tc-display-html',
2581
+ template: "<ng-content></ng-content>",
2582
+ styles: [":host{display:block;width:100%}"]
2583
+ },] }
2584
+ ];
2585
+ TcDisplayHtmlComponent.ctorParameters = () => [];
2586
+
2587
+ class TcDisplayPlainComponent {
2588
+ constructor() { }
2589
+ }
2590
+ TcDisplayPlainComponent.decorators = [
2488
2591
  { type: Component, args: [{
2489
- selector: 'xuilib-search-judicials',
2490
- template: "<div class=\"govuk-form-group\">\n <input id=\"inputSelectPerson{{idValue}}\" [placeholder]=\"placeholderContent\" [formControl]=\"formGroup.controls.formControl\"\n [matAutocomplete]=\"autoComplete\" (keydown)=\"onKeyDown()\" (keyup)=\"onKeyUp($event)\" (focus)=\"onFocus()\"\n class=\"govuk-input\" [attr.disabled]=\"!disabled ? null: disabled\" [value]=\"getControlValueDisplayText()\"\n #inputSelection>\n <mat-autocomplete autoActiveFirstOption #autoComplete=\"matAutocomplete\">\n <mat-option *ngFor=\"let judicial of displayedJudicialsDuplicationFiltered\" class=\"select-option\"\n [value]=\"getDisplayName(judicial)\" (onSelectionChange)=\"onSelectionChange(judicial)\"\n [ngClass]=\"{'hide-autocomplete': !showAutocomplete}\">\n {{ getDisplayName(judicial) }}\n </mat-option>\n <mat-option class=\"select-option\"\n *ngIf=\"!displayedJudicialsDuplicationFiltered?.length && showAutocomplete && !searchInProgress\">\n {{ 'No results found' }}</mat-option>\n </mat-autocomplete>\n</div>\n",
2491
- styles: [".hide-autocomplete{display:none}.mat-option:hover{background:#2596be}.mat-option.select-option:hover{background:#1d70b8;color:#fff}"]
2592
+ selector: 'xuilib-tc-display-plain',
2593
+ template: "<ng-content></ng-content>",
2594
+ styles: [":host{display:block;width:100%}"]
2492
2595
  },] }
2493
2596
  ];
2494
- SearchJudicialsComponent.ctorParameters = () => [
2495
- { type: FindAPersonService },
2496
- { type: FormBuilder }
2597
+ TcDisplayPlainComponent.ctorParameters = () => [];
2598
+
2599
+ class TermsAndConditionsComponent {
2600
+ constructor() { }
2601
+ }
2602
+ TermsAndConditionsComponent.decorators = [
2603
+ { type: Component, args: [{
2604
+ selector: 'xuilib-terms-and-conditions',
2605
+ template: "<ng-container [ngSwitch]=\"document.mimeType\">\n <xuilib-tc-display-html *ngSwitchCase=\"'text/html'\">\n <div [innerHTML]=\"document.content\"></div>\n </xuilib-tc-display-html>\n <xuilib-tc-display-plain *ngSwitchCase=\"'text/plain'\">\n {{ document.content }}\n </xuilib-tc-display-plain>\n <div *ngSwitchDefault>\n An error occured. Please try again.\n </div>\n</ng-container>\n",
2606
+ styles: [":host{display:block;width:100%}"]
2607
+ },] }
2497
2608
  ];
2498
- SearchJudicialsComponent.propDecorators = {
2499
- control: [{ type: Input }],
2500
- disabled: [{ type: Input }],
2501
- selectedJudicials: [{ type: Input }],
2502
- submitted: [{ type: Input }],
2503
- placeholderContent: [{ type: Input }],
2504
- showAutocomplete: [{ type: Input }],
2505
- displayedJudicials: [{ type: Input }],
2506
- judicialChanged: [{ type: Output }],
2507
- idValue: [{ type: Input }],
2508
- errorMessage: [{ type: Input }],
2509
- serviceId: [{ type: Input }],
2510
- autoCompleteInputBox: [{ type: ViewChild, args: ['inputSelection', { read: ElementRef, static: true },] }]
2609
+ TermsAndConditionsComponent.ctorParameters = () => [];
2610
+ TermsAndConditionsComponent.propDecorators = {
2611
+ document: [{ type: Input }]
2511
2612
  };
2512
2613
 
2513
- class FindPersonComponent {
2514
- constructor(findPersonService, cd) {
2515
- this.findPersonService = findPersonService;
2516
- this.cd = cd;
2517
- this.personSelected = new EventEmitter();
2518
- this.personFieldChanged = new EventEmitter();
2519
- this.boldTitle = 'Find the person';
2520
- this.subTitle = 'Type the name of the person and select them.';
2521
- this.domain = PersonRole.ALL;
2522
- this.findPersonGroup = new FormGroup({});
2523
- this.submitted = true;
2524
- this.userIncluded = false;
2525
- this.placeholderContent = '';
2526
- this.isNoResultsShown = true;
2527
- this.showUpdatedColor = false;
2528
- this.selectedPersons = [];
2529
- this.errorMessage = 'You must select a name';
2530
- this.idValue = '';
2531
- this.services = ['IA'];
2532
- this.disabled = null;
2533
- this.showAutocomplete = false;
2534
- this.filteredOptions = [];
2535
- this.minSearchCharacters = 2;
2536
- }
2537
- ngOnDestroy() {
2538
- if (this.sub) {
2539
- this.sub.unsubscribe();
2540
- }
2541
- }
2542
- ngOnInit() {
2543
- this.findPersonControl = new FormControl(this.selectedPerson);
2544
- this.findPersonGroup.addControl('findPersonControl', this.findPersonControl);
2545
- this.sub = this.findPersonControl.valueChanges.pipe(tap(() => this.showAutocomplete = false), tap(() => this.filteredOptions = []), debounceTime(300), tap((searchTerm) => typeof searchTerm === 'string' ? this.personSelected.emit(null) : void 0), filter((searchTerm) => searchTerm && searchTerm.length > this.minSearchCharacters), switchMap((searchTerm) => this.filter(searchTerm).pipe(tap(() => this.showAutocomplete = true), catchError(() => this.filteredOptions = [])))).subscribe((people) => {
2546
- this.filteredOptions = people;
2547
- this.cd.detectChanges();
2548
- });
2614
+ class UserDetailsComponent {
2615
+ constructor() {
2616
+ this.showEditLink = false;
2617
+ this.showHelpLink = false;
2618
+ this.suspendUserEvent = new EventEmitter();
2619
+ this.showSuspendUserButton = false;
2620
+ this.reinvite = new EventEmitter();
2549
2621
  }
2550
- filter(searchTerm) {
2551
- const findJudicialPeople = this.findPersonService.find({ searchTerm, userRole: this.domain, services: this.services, userIncluded: this.userIncluded, assignedUser: this.assignedUser });
2552
- const findCaseworkersOrAdmins = this.findPersonService.findCaseworkers({ searchTerm, userRole: this.domain, services: this.services, userIncluded: this.userIncluded, assignedUser: this.assignedUser });
2553
- if (searchTerm && searchTerm.length > this.minSearchCharacters) {
2554
- switch (this.domain) {
2555
- case PersonRole.JUDICIAL: {
2556
- return findJudicialPeople.pipe(map(persons => {
2557
- const ids = this.selectedPersons.map(({ id }) => id);
2558
- return persons.filter(({ id }) => !ids.includes(id));
2559
- }));
2560
- }
2561
- case PersonRole.ALL: {
2562
- return zip(findJudicialPeople, findCaseworkersOrAdmins).pipe(map(separatePeople => separatePeople[0].concat(separatePeople[1])));
2563
- }
2564
- case PersonRole.CASEWORKER:
2565
- case PersonRole.ADMIN: {
2566
- return findCaseworkersOrAdmins;
2567
- }
2568
- default: {
2569
- return of([]);
2570
- }
2571
- }
2572
- }
2573
- return of([]);
2622
+ reinviteClick(user) {
2623
+ this.reinvite.emit(user);
2574
2624
  }
2575
- onSelectionChange(selectedPerson) {
2576
- this.personSelected.emit(selectedPerson);
2577
- this.findPersonControl.setValue(this.getDisplayName(selectedPerson), { emitEvent: false, onlySelf: true });
2625
+ suspendUser(suspendUser) {
2626
+ this.suspendUserEvent.emit(suspendUser);
2578
2627
  }
2579
- getDisplayName(selectedPerson) {
2580
- if (!selectedPerson) {
2581
- return '';
2582
- }
2583
- if (selectedPerson.domain === PersonRole.JUDICIAL && selectedPerson.knownAs) {
2584
- return `${selectedPerson.knownAs} (${selectedPerson.email})`;
2628
+ userHasRole(theRole) {
2629
+ if (this.user && this.user.roles) {
2630
+ return this.user.roles.includes(theRole);
2585
2631
  }
2586
- return selectedPerson.email ? `${selectedPerson.name} (${selectedPerson.email})` : selectedPerson.name;
2587
- }
2588
- onInput() {
2589
- this.personFieldChanged.emit();
2632
+ return false;
2590
2633
  }
2591
2634
  }
2592
- FindPersonComponent.decorators = [
2635
+ UserDetailsComponent.decorators = [
2593
2636
  { type: Component, args: [{
2594
- selector: 'xuilib-find-person',
2595
- template: "<h1 class=\"govuk-heading-l\" *ngIf=\"title && title.length\">\n <span class=\"govuk-caption-l\">{{title}}</span>\n {{boldTitle}}\n</h1>\n<div class=\"govuk-form-group\" [formGroup]=\"findPersonGroup\"\n [ngClass]=\"{'form-group-error': findPersonGroup.get('findPersonControl').invalid && submitted}\">\n <fieldset class=\"govuk-fieldset\" aria-describedby=\"sub-title-hint\">\n <div id=\"sub-title-hint\" class=\"govuk-hint\" *ngIf=\"subTitle && subTitle.length\">\n {{subTitle}}\n </div>\n <span id=\"validation-error\" class=\"govuk-error-message\" *ngIf=\"findPersonGroup && findPersonGroup.errors\">\n <span class=\"govuk-visually-hidden\">Error:</span>{{findPersonGroup.errors.error ? findPersonGroup.errors.error : errorMessage}}\n </span>\n <input id=\"inputSelectPerson{{idValue}}\" type=\"text\" aria-label=\"select a person\"\n formControlName=\"findPersonControl\"\n [matAutocomplete]=\"auto\"\n class=\"govuk-input govuk-!-width-one-third\"\n [placeholder]=\"placeholderContent\"\n [attr.disabled]=\"disabled\"\n (input)=\"onInput()\">\n <mat-autocomplete autoActiveFirstOption #auto=\"matAutocomplete\" (optionSelected)=\"onSelectionChange($event.option.value)\">\n <mat-option *ngFor=\"let option of filteredOptions\"\n [value]=\"option\"\n [ngClass]=\"{'hide-autocomplete': !showAutocomplete, 'select-option': showUpdatedColor}\">\n {{getDisplayName(option)}}\n </mat-option>\n <mat-option [ngClass]=\"{'select-option': showUpdatedColor}\" *ngIf=\"isNoResultsShown && !filteredOptions.length && showAutocomplete\">No results found</mat-option>\n </mat-autocomplete>\n </fieldset>\n</div>\n",
2596
- styles: [".mat-option:hover{background:#2596be}.mat-option.select-option:hover{background:#1d70b8;color:#fff}.hide-autocomplete{display:none}"]
2637
+ selector: 'xuilib-user-details',
2638
+ template: "<div class=\"govuk-warning-text\" *ngIf=\"warningTitle && warningTitle !== ''\">\n<span class=\"govuk-warning-text__icon\">!</span>\n<strong class=\"govuk-warning-text__text\">\n {{ warningTitle }}\n</strong>\n</div>\n<table class=\"govuk-table\" *ngIf=\"user\">\n <tbody class=\"govuk-table__body\">\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header\" scope=\"row\">Name</th>\n <td class=\"govuk-table__cell\">{{user.fullName}}</td>\n <td class=\"govuk-table__cell\"></td>\n </tr>\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header\" scope=\"row\">Email address</th>\n <td class=\"govuk-table__cell\">{{user.email}}</td>\n <td class=\"govuk-table__cell\"></td>\n </tr>\n <tr class=\"govuk-table__row\" *ngIf=\"!user.resendInvite\">\n <th class=\"govuk-table__header\" scope=\"row\">Permissions</th>\n <td class=\"govuk-table__cell\">\n <div *ngIf=\"user.manageOrganisations === 'Yes'\">Manage organisations</div>\n <div *ngIf=\"user.manageUsers === 'Yes'\">Manage users</div>\n <div *ngIf=\"user.manageCases === 'Yes'\">Manage cases</div>\n <div *ngIf=\"userHasRole('pui-caa')\">Case access administrator</div>\n <div *ngIf=\"userHasRole('pui-finance-manager')\">Manage fee accounts</div>\n </td>\n <td class=\"govuk-table__cell\"><a *ngIf=\"editPermissionRouterLink && showEditLink\" [routerLink]=\"editPermissionRouterLink\">Change <span class=\"govuk-visually-hidden\">roles</span></a></td>\n </tr>\n </tbody>\n</table>\n<button *ngIf=\"showSuspendUserButton\" class=\"govuk-button govuk-button--warning\" (click)=\"suspendUser(user)\">\n Suspend account\n</button>\n<div *ngIf=\"user && user.resendInvite\">\n <div class=\"govuk-inset-text\">\n <p>This user has already been invited but has not activated their account.</p>\n <p>If you resend an invitation, they'll receive an email from HM Courts and Tribunals to finish setting up their account.</p>\n <p>You can't invite the same user more than once an hour.</p>\n </div>\n <a role=\"button\" draggable=\"false\" class=\"govuk-button\" (click)=\"reinviteClick(user)\" id=\"resend-invite-button\">\n Resend invitation\n </a>\n</div>\n<p class=\"govuk-body\" *ngIf=\"showHelpLink && suspendHelpLink\"><a [routerLink]=\"suspendHelpLink\" target=\"_blank\">Get help</a> to reactivate this account.</p>\n",
2639
+ styles: [":host{display:block}"]
2597
2640
  },] }
2598
2641
  ];
2599
- FindPersonComponent.ctorParameters = () => [
2600
- { type: FindAPersonService },
2601
- { type: ChangeDetectorRef }
2602
- ];
2603
- FindPersonComponent.propDecorators = {
2604
- personSelected: [{ type: Output }],
2605
- personFieldChanged: [{ type: Output }],
2606
- title: [{ type: Input }],
2607
- boldTitle: [{ type: Input }],
2608
- subTitle: [{ type: Input }],
2609
- domain: [{ type: Input }],
2610
- findPersonGroup: [{ type: Input }],
2611
- selectedPerson: [{ type: Input }],
2612
- submitted: [{ type: Input }],
2613
- userIncluded: [{ type: Input }],
2614
- assignedUser: [{ type: Input }],
2615
- placeholderContent: [{ type: Input }],
2616
- isNoResultsShown: [{ type: Input }],
2617
- showUpdatedColor: [{ type: Input }],
2618
- selectedPersons: [{ type: Input }],
2619
- errorMessage: [{ type: Input }],
2620
- idValue: [{ type: Input }],
2621
- services: [{ type: Input }],
2622
- disabled: [{ type: Input }]
2642
+ UserDetailsComponent.propDecorators = {
2643
+ user: [{ type: Input }],
2644
+ editPermissionRouterLink: [{ type: Input }],
2645
+ warningTitle: [{ type: Input }],
2646
+ showEditLink: [{ type: Input }],
2647
+ showHelpLink: [{ type: Input }],
2648
+ suspendHelpLink: [{ type: Input }],
2649
+ suspendUserEvent: [{ type: Output }],
2650
+ showSuspendUserButton: [{ type: Input }],
2651
+ reinvite: [{ type: Output }]
2623
2652
  };
2624
2653
 
2625
- /**
2626
- * Main Page Wrapper
2627
- * Responsible for:
2628
- * Wrapping content within the gov-uk html elements bellow
2629
- * @prop showBackLink - switch for back link
2630
- * @prop appHeaderTitle = appHeaderTitle
2631
- * @prop appFunctionalTitle = appFunctionalTitle
2632
- * @prop summaryErrors list of errors
2633
- * @prop back link, appHeaderTitle (appHeaderTitle), summaryErrors (array of errors)
2634
- */
2635
- class ExuiPageWrapperComponent {
2636
- constructor() { }
2654
+ class UserListComponent {
2655
+ constructor() {
2656
+ this.users = [];
2657
+ this.userClick = new EventEmitter();
2658
+ this.pageChange = new EventEmitter();
2659
+ }
2660
+ ngOnInit() {
2661
+ this.pagination = { itemsPerPage: 50, currentPage: this.currentPageNumber, totalItems: this.pageTotalSize };
2662
+ }
2663
+ onUserClick(user) {
2664
+ this.userClick.emit(user);
2665
+ }
2666
+ emitPageClickEvent(pageNumber) {
2667
+ this.currentPageNumber = pageNumber;
2668
+ this.pageChange.emit(pageNumber);
2669
+ }
2637
2670
  }
2638
- ExuiPageWrapperComponent.decorators = [
2671
+ UserListComponent.decorators = [
2639
2672
  { type: Component, args: [{
2640
- selector: 'exui-page-wrapper',
2641
- template: "<div class=\"page\">\n <a *ngIf=\"backLink\" [routerLink]=\"backLink\" class=\"govuk-back-link\">Back</a>\n <div class=\"govuk-width-container\">\n <main id=\"content\" role=\"main\" class=\"govuk-main-wrapper\">\n <div class=\"govuk-grid-row\">\n <h1 *ngIf=\"title\" class=\"govuk-heading-xl\">\n <span *ngIf=\"fnTitle\" class=\"govuk-caption-xl\">{{fnTitle}}</span>\n {{title}}\n </h1>\n <ng-content>\n\n </ng-content>\n </div>\n </main>\n </div>\n</div>\n",
2642
- styles: [".page{width:100%}"]
2673
+ selector: 'xuilib-user-list',
2674
+ template: "<table class=\"govuk-table\">\n\n <thead clas=\"govuk-table__head\">\n <tr class=\"govuk-table__row\">\n <th class=\"govuk-table__header\" scope=\"col\">Name</th>\n <th class=\"govuk-table__header\" scope=\"col\">Email</th>\n <th class=\"govuk-table__header\" scope=\"col\">Status</th>\n </tr>\n </thead>\n <tbody class=\"govuk-table__body\">\n <ng-container *ngFor=\"let u of users | paginate: { itemsPerPage: pagination.itemsPerPage, currentPage: currentPageNumber, totalItems: pagination.totalItems }\">\n <tr class=\"govuk-table__row\" data-selector=\"table-row\">\n <td class=\"govuk-table__cell\" data-selector=\"table-cell\">\n <a class=\"govuk-link\" [attr.title]=\"u.routerLinkTitle\" [routerLink]=\"u.routerLink\" (click)=\"onUserClick(u)\">{{ u.fullName }}</a>\n </td>\n <td class=\"govuk-table__cell\" data-selector=\"table-cell\">{{ u.email }}</td>\n <td class=\"govuk-table__cell\" data-selector=\"table-cell\">{{ u.status }}</td>\n </tr>\n </ng-container>\n </tbody>\n</table>\n<xuilib-hmcts-pagination (pageChange)=\"emitPageClickEvent($event)\" [pageSize]=\"pagination.itemsPerPage\"></xuilib-hmcts-pagination>\n",
2675
+ styles: [":host{display:block}"]
2643
2676
  },] }
2644
2677
  ];
2645
- ExuiPageWrapperComponent.ctorParameters = () => [];
2646
- ExuiPageWrapperComponent.propDecorators = {
2647
- backLink: [{ type: Input }],
2648
- title: [{ type: Input }],
2649
- fnTitle: [{ type: Input }]
2678
+ UserListComponent.propDecorators = {
2679
+ users: [{ type: Input }],
2680
+ currentPageNumber: [{ type: Input }],
2681
+ pageTotalSize: [{ type: Input }],
2682
+ userClick: [{ type: Output }],
2683
+ pageChange: [{ type: Output }]
2650
2684
  };
2651
2685
 
2652
2686
  class FeatureToggleDirective {
@@ -3769,10 +3803,6 @@ LoadingService.decorators = [
3769
3803
  },] }
3770
3804
  ];
3771
3805
 
3772
- /*
3773
- * Public API Surface of exui-common-lib
3774
- */
3775
-
3776
3806
  const COMMON_COMPONENTS = [
3777
3807
  ExuiPageWrapperComponent,
3778
3808
  TermsAndConditionsComponent,
@@ -3839,12 +3869,14 @@ const COMMON_SERVICES = [
3839
3869
  LaunchDarklyService,
3840
3870
  FilterService,
3841
3871
  FindAPersonService,
3872
+ FeatureToggleService,
3842
3873
  GoogleAnalyticsService,
3843
3874
  GoogleTagManagerService,
3844
3875
  LoadingService,
3845
3876
  LocationService,
3846
3877
  ManageSessionServices,
3847
3878
  SessionStorageService,
3879
+ RoleService,
3848
3880
  TimeoutNotificationsService
3849
3881
  ];
3850
3882
  const ɵ0 = windowProvider;
@@ -3873,78 +3905,11 @@ ExuiCommonLibModule.decorators = [
3873
3905
  exports: [
3874
3906
  ...COMMON_COMPONENTS,
3875
3907
  ...GOV_UI_COMPONENTS,
3876
- PaginatePipe
3908
+ PaginatePipe,
3877
3909
  ]
3878
3910
  },] }
3879
3911
  ];
3880
3912
 
3881
- class GovUiService {
3882
- constructor() { }
3883
- }
3884
- GovUiService.ɵprov = i0.ɵɵdefineInjectable({ factory: function GovUiService_Factory() { return new GovUiService(); }, token: GovUiService, providedIn: "root" });
3885
- GovUiService.decorators = [
3886
- { type: Injectable, args: [{
3887
- providedIn: 'root'
3888
- },] }
3889
- ];
3890
- GovUiService.ctorParameters = () => [];
3891
-
3892
- function checkboxesBeCheckedValidator(minRequired = 1) {
3893
- return function validate(formGroup) {
3894
- let checked = 0;
3895
- Object.keys(formGroup.controls).forEach(key => {
3896
- const control = formGroup.controls[key];
3897
- if (control.value === true) {
3898
- checked++;
3899
- }
3900
- });
3901
- if (checked < minRequired) {
3902
- return {
3903
- requireOneCheckboxToBeChecked: true,
3904
- };
3905
- }
3906
- return null;
3907
- };
3908
- }
3909
-
3910
- function dateValidator() {
3911
- return function validate(formGroup) {
3912
- const d = new Date(parseInt(formGroup.controls.day.value, 10), parseInt(formGroup.controls.month.value, 10) - 1, parseInt(formGroup.controls.year.value, 10) - 1);
3913
- function isValidDate(val) {
3914
- return val instanceof Date && !isNaN(+d);
3915
- }
3916
- if (!isValidDate(d)) {
3917
- return {
3918
- dateIsInvalid: true,
3919
- };
3920
- }
3921
- return null;
3922
- };
3923
- }
3924
-
3925
- function radioGroupValidator() {
3926
- return function validate(formGroup) {
3927
- if (formGroup.controls) {
3928
- for (const control in formGroup.controls) {
3929
- if (!formGroup.controls[control].valid) {
3930
- return {
3931
- isRadioGroupInvalid: true,
3932
- };
3933
- }
3934
- }
3935
- }
3936
- return null;
3937
- };
3938
- }
3939
-
3940
- /*
3941
- * Public API Surface of gov-ui
3942
- */
3943
-
3944
- /*
3945
- * Public API Surface of gov-ui
3946
- */
3947
-
3948
3913
  /*
3949
3914
  * Public API Surface of exui-common-lib
3950
3915
  */
@@ -3953,5 +3918,5 @@ function radioGroupValidator() {
3953
3918
  * Generated bundle index. Do not edit.
3954
3919
  */
3955
3920
 
3956
- export { AccessibilityComponent, AnonymousFeatureUser, BadgeColour, COMMON_COMPONENTS, COMMON_SERVICES, CaseSharingStateService, CheckboxListComponent, ContactDetailsComponent, CookieBannerComponent, CookieService, DateBadgeColour, DueDateComponent, ExuiCommonLibModule, ExuiPageWrapperComponent, FeatureToggleDirective, FeatureToggleGuard, FeatureToggleService, FilterService, FindAPersonService, FindLocationComponent, FindPersonComponent, GOV_UI_COMPONENTS, GenericFilterComponent, GoogleAnalyticsService, GoogleTagManagerService, GovUiService, GovUkCheckboxComponent, GovUkCheckboxesComponent, GovUkDateComponent, GovUkErrorMessageComponent, GovUkFieldsetComponent, GovUkFileUploadComponent, GovUkFormGroupWrapperComponent, GovUkInputComponent, GovUkLabelComponent, GovUkRadioComponent, GovUkRadiosComponent, GovUkSelectComponent, GovUkTextareaComponent, GovukTableColumnConfig, GovukTableComponent, HasLoadingState, HmctsBannerComponent, HmctsErrorSummaryComponent, HmctsIdentityBarComponent, HmctsMainWrapperComponent, HmctsPaginationComponent, HmctsPrimaryNavigationComponent, HmctsSessionDialogComponent, HmctsSubNavigationComponent, InviteUserFormComponent, InviteUserPermissionComponent, LaunchDarklyService, LetContext, LetDirective, LoadingService, LoadingSpinnerComponent, LocationService, LoggedInFeatureUser, ManageSessionServices, PaginationComponent, PersonRole, RadioFilterFieldConfig, RemoveHostDirective, RoleCategory, RoleGuard, RoleMatching, RoleService, SECONDS_IN_A_DAY, SearchJudicialsComponent, SearchLocationComponent, SearchVenueComponent, SelectedCaseComponent, SelectedCaseConfirmComponent, SelectedCaseListComponent, ServiceMessageComponent, ServiceMessagesComponent, SessionStorageService, ShareCaseComponent, ShareCaseConfirmComponent, TabComponent, TcConfirmComponent, TcDisplayHtmlComponent, TcDisplayPlainComponent, TermsAndConditionsComponent, TimeoutNotificationsService, UserDetailsComponent, UserListComponent, UserSelectComponent, checkboxesBeCheckedValidator, dateValidator, radioGroupValidator, windowProvider, windowToken, ɵ0, ExuiPageWrapperComponent as ɵa, TermsAndConditionsComponent as ɵb, ServiceMessageComponent as ɵba, ServiceMessagesComponent as ɵbb, LoadingSpinnerComponent as ɵbc, GenericFilterComponent as ɵbd, FilterService as ɵbe, CookieBannerComponent as ɵbf, CookieService as ɵbg, FindPersonComponent as ɵbh, FindAPersonService as ɵbi, SessionStorageService as ɵbj, SearchJudicialsComponent as ɵbk, FindLocationComponent as ɵbl, SearchLocationComponent as ɵbm, LocationService as ɵbn, SearchVenueComponent as ɵbo, PaginationComponent as ɵbp, HmctsIdentityBarComponent as ɵbq, HmctsPaginationComponent as ɵbr, HmctsSubNavigationComponent as ɵbs, HmctsPrimaryNavigationComponent as ɵbt, HmctsErrorSummaryComponent as ɵbu, HmctsMainWrapperComponent as ɵbv, HmctsBannerComponent as ɵbw, GovukTableComponent as ɵbx, GovUkInputComponent as ɵby, GovUkCheckboxComponent as ɵbz, TcDisplayHtmlComponent as ɵc, GovUkFormGroupWrapperComponent as ɵca, GovUkLabelComponent as ɵcb, GovUkErrorMessageComponent as ɵcc, GovUkFieldsetComponent as ɵcd, GovUkDateComponent as ɵce, GovUkCheckboxesComponent as ɵcf, GovUkRadioComponent as ɵcg, GovUkRadiosComponent as ɵch, GovUkSelectComponent as ɵci, GovUkTextareaComponent as ɵcj, GovUkFileUploadComponent as ɵck, RemoveHostDirective as ɵcl, CaseSharingStateService as ɵcm, CookieService as ɵcn, LaunchDarklyService as ɵco, FilterService as ɵcp, FindAPersonService as ɵcq, GoogleAnalyticsService as ɵcr, GoogleTagManagerService as ɵcs, LoadingService as ɵct, LocationService as ɵcu, ManageSessionServices as ɵcv, SessionStorageService as ɵcw, TimeoutNotificationsService as ɵcx, TcDisplayPlainComponent as ɵd, TcConfirmComponent as ɵe, ContactDetailsComponent as ɵf, FeatureToggleDirective as ɵg, FeatureToggleService as ɵh, LetContext as ɵi, LetDirective as ɵj, HmctsSessionDialogComponent as ɵk, UserListComponent as ɵl, UserDetailsComponent as ɵm, InviteUserPermissionComponent as ɵn, InviteUserFormComponent as ɵo, ShareCaseComponent as ɵp, UserSelectComponent as ɵq, CaseSharingStateService as ɵr, ShareCaseConfirmComponent as ɵs, SelectedCaseListComponent as ɵt, SelectedCaseComponent as ɵu, SelectedCaseConfirmComponent as ɵv, TabComponent as ɵw, AccessibilityComponent as ɵx, DueDateComponent as ɵy, CheckboxListComponent as ɵz };
3921
+ export { AccessibilityComponent, BadgeColour, CaseSharingStateService, CheckboxListComponent, ContactDetailsComponent, CookieBannerComponent, CookieService, DueDateComponent, ExuiCommonLibModule, ExuiPageWrapperComponent, FeatureToggleDirective, FeatureToggleGuard, FeatureToggleService, FilterService, FindAPersonService, FindLocationComponent, FindPersonComponent, GenericFilterComponent, GoogleAnalyticsService, GoogleTagManagerService, GovUkCheckboxComponent, GovUkCheckboxesComponent, GovUkDateComponent, GovUkErrorMessageComponent, GovUkFieldsetComponent, GovUkFileUploadComponent, GovUkFormGroupWrapperComponent, GovUkInputComponent, GovUkLabelComponent, GovUkRadioComponent, GovUkRadiosComponent, GovUkSelectComponent, GovUkTextareaComponent, GovukTableComponent, HmctsBannerComponent, HmctsErrorSummaryComponent, HmctsIdentityBarComponent, HmctsMainWrapperComponent, HmctsPaginationComponent, HmctsPrimaryNavigationComponent, HmctsSessionDialogComponent, HmctsSubNavigationComponent, InviteUserFormComponent, InviteUserPermissionComponent, LaunchDarklyService, LetDirective, LoadingService, LoadingSpinnerComponent, LocationService, ManageSessionServices, PaginationComponent, PersonRole, RemoveHostDirective, RoleGuard, RoleMatching, RoleService, SearchJudicialsComponent, SearchLocationComponent, SearchVenueComponent, SelectedCaseComponent, SelectedCaseConfirmComponent, SelectedCaseListComponent, ServiceMessageComponent, ServiceMessagesComponent, SessionStorageService, ShareCaseComponent, ShareCaseConfirmComponent, TabComponent, TcConfirmComponent, TcDisplayHtmlComponent, TcDisplayPlainComponent, TermsAndConditionsComponent, TimeoutNotificationsService, UserDetailsComponent, UserListComponent, UserSelectComponent, LetContext as ɵa, windowToken as ɵb, windowProvider as ɵc };
3957
3922
  //# sourceMappingURL=hmcts-rpx-xui-common-lib.js.map