From e78b7256eb711717a0153d095109b73a7ff7ce4b Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 19 Feb 2024 15:11:10 +0000 Subject: [PATCH 01/60] update form with updated fields --- home/forms/search.py | 27 +++++++++-- home/service/search.py | 28 +++++++++--- home/views.py | 1 + templates/partial/filter1.html | 84 ++++++++++++++++++++++++++++++++++ templates/search.html | 2 +- 5 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 templates/partial/filter1.html diff --git a/home/forms/search.py b/home/forms/search.py index b54b435f..625a92ea 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -10,6 +10,7 @@ def get_domain_choices(): # facets = client.search_facets() # domain_list = facets.options("domains") return [ + ("Default", "Select ..."), ("urn:li:domain:HMCTS", "HMCTS"), ("urn:li:domain:HMPPS", "HMPPS"), ("urn:li:domain:HQ", "HQ"), @@ -78,9 +79,26 @@ class SearchForm(forms.Form): required=False, widget=forms.TextInput(attrs={"class": "govuk-input search-input"}), ) - domains = forms.MultipleChoiceField( + domain = forms.ChoiceField( choices=get_domain_choices, required=False, + widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), + ) + subdomains = forms.ChoiceField( + choices=get_subdomain_choices, + required=False, + widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), + ) + classifications = forms.MultipleChoiceField( + choices=get_classification_choices, + required=False, + widget=forms.CheckboxSelectMultiple( + attrs={"class": "govuk-checkboxes__input", "form": "searchform"} + ), + ) + availabilities = forms.MultipleChoiceField( + choices=get_availability_choices(), + required=False, widget=forms.CheckboxSelectMultiple( attrs={"class": "govuk-checkboxes__input", "form": "searchform"} ), @@ -107,9 +125,8 @@ def encode_without_filter(self, filter_to_remove): """Preformat hrefs to drop individual filters""" # Deepcopy the cleaned data dict to avoid modifying it inplace query_params = deepcopy(self.cleaned_data) - - query_params["domains"].remove(filter_to_remove) - if len(query_params["domains"]) == 0: + if filter_to_remove == query_params.get("domains"): query_params.pop("domains") - + elif filter_to_remove == query_params.get("subdomains"): + query_params.pop("subdomains") return f"?{urlencode(query_params, doseq=True)}" diff --git a/home/service/search.py b/home/service/search.py index 40c4c5da..e7881b06 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -1,6 +1,10 @@ from typing import Any -from data_platform_catalogue.search_types import MultiSelectFilter, SortOption +from data_platform_catalogue.search_types import ( + MultiSelectFilter, + SingleSelectFilter, + SortOption, +) from django.core.paginator import Paginator from home.forms.search import SearchForm, get_subdomain_choices @@ -53,7 +57,6 @@ def _get_search_results(self, page: str, items_per_page: int): sort=sort_option, count=items_per_page, ) - return results def _get_paginator(self, items_per_page: int) -> Paginator: @@ -69,13 +72,24 @@ def _get_context(self) -> dict[str, Any]: page_title = "Search - Data catalogue" if self.form.is_bound: - label_clear_href = { - filter.split(":")[-1]: self.form.encode_without_filter(filter) - for filter in self.form.cleaned_data.get("domains", []) - } + label_clear_href = {} + domain = self.form.cleaned_data.get("domain") + subdomain = self.form.cleaned_data.get("subdomains") + if domain: + label_clear_href[domain.split(":")[-1]] = ( + self.form.encode_without_filter( + filter_to_remove=self.form.cleaned_data.get("domain") + ) + ) + if subdomain: + label_clear_href[subdomain.split(":")[-1]] = ( + self.form.encode_without_filter( + filter_to_remove=self.form.cleaned_data.get("subdomains") + ) + ) else: label_clear_href = None - + print(label_clear_href) context = { "form": self.form, "results": self.results.page_results, diff --git a/home/views.py b/home/views.py index 5937a65d..28d02ce5 100644 --- a/home/views.py +++ b/home/views.py @@ -24,6 +24,7 @@ def details_view(request, id): def search_view(request, page: str = "1"): + print(request.GET) new_search = request.GET.get("new", "") if new_search: form = SearchForm() diff --git a/templates/partial/filter1.html b/templates/partial/filter1.html new file mode 100644 index 00000000..d4940961 --- /dev/null +++ b/templates/partial/filter1.html @@ -0,0 +1,84 @@ +{% load future %} +
+
+
+
+

Filter

+
+
+
+
+ +
+
+
+
+

Selected filters

+
+ +
+ {% if form.domains.value %} +

Domain

+ + {% endif %} +
+
+ +
+ + {{form.domain}} + +
+
+ + {{form.subdomains}} +
+
+
+ Security Classification +
+ {% for classification_option in form.classifications %} +
+ {{ classification_option.tag}} + +
+ {% endfor %} +
+
+
+
+
+ Availability +
+ {% for availability_option in form.availabilities %} +
+ {{ availability_option.tag}} + +
+ {% endfor %} +
+
+
+
+
+
+
diff --git a/templates/search.html b/templates/search.html index 03436bea..fbfd35eb 100644 --- a/templates/search.html +++ b/templates/search.html @@ -24,7 +24,7 @@

Find MOJ Data

- {% include "partial/filter.html" %} + {% include "partial/filter1.html" %}

{{total_results|intcomma}} Results

{% include "partial/sort.html" %} From 0ec2c6dbdb3764e75ba83af8453b958e6dd14a52 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 19 Feb 2024 15:11:36 +0000 Subject: [PATCH 02/60] update form with updated fields --- home/service/search.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index e7881b06..39b5f5d0 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -1,10 +1,8 @@ from typing import Any -from data_platform_catalogue.search_types import ( - MultiSelectFilter, - SingleSelectFilter, - SortOption, -) +from data_platform_catalogue.search_types import (MultiSelectFilter, + SingleSelectFilter, + SortOption) from django.core.paginator import Paginator from home.forms.search import SearchForm, get_subdomain_choices @@ -65,7 +63,6 @@ def _get_paginator(self, items_per_page: int) -> Paginator: return Paginator(pages_list, items_per_page) def _get_context(self) -> dict[str, Any]: - if self.form["query"].value(): page_title = f'Search for "{self.form["query"].value()}" - Data catalogue' else: @@ -76,16 +73,16 @@ def _get_context(self) -> dict[str, Any]: domain = self.form.cleaned_data.get("domain") subdomain = self.form.cleaned_data.get("subdomains") if domain: - label_clear_href[domain.split(":")[-1]] = ( - self.form.encode_without_filter( - filter_to_remove=self.form.cleaned_data.get("domain") - ) + label_clear_href[ + domain.split(":")[-1] + ] = self.form.encode_without_filter( + filter_to_remove=self.form.cleaned_data.get("domain") ) if subdomain: - label_clear_href[subdomain.split(":")[-1]] = ( - self.form.encode_without_filter( - filter_to_remove=self.form.cleaned_data.get("subdomains") - ) + label_clear_href[ + subdomain.split(":")[-1] + ] = self.form.encode_without_filter( + filter_to_remove=self.form.cleaned_data.get("subdomains") ) else: label_clear_href = None From 7fc7684e7194dcd426af26c221fa071031e230e0 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Tue, 20 Feb 2024 23:01:55 +0000 Subject: [PATCH 03/60] implement custom property search --- core/settings.py | 9 ++-- home/forms/search.py | 57 ++++++++++++++++++---- home/service/search.py | 86 ++++++++++++++++++++++++---------- home/views.py | 2 +- templates/partial/filter.html | 32 ++++++++++--- templates/partial/filter1.html | 84 --------------------------------- templates/search.html | 2 +- 7 files changed, 140 insertions(+), 132 deletions(-) delete mode 100644 templates/partial/filter1.html diff --git a/core/settings.py b/core/settings.py index 70bdb09c..e906359d 100644 --- a/core/settings.py +++ b/core/settings.py @@ -86,10 +86,8 @@ LANGUAGE_CODE = "en-gb" -TIME_ZONE = "UTC" - -USE_I18N = True - +TIME_ZONE = "Europe/London" +USE_I18N = False USE_TZ = True @@ -113,8 +111,7 @@ "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) -SAMPLE_SEARCH_RESULTS_FILENAME = BASE_DIR / \ - "sample_data/sample_search_page.yaml" +SAMPLE_SEARCH_RESULTS_FILENAME = BASE_DIR / "sample_data/sample_search_page.yaml" with open(SAMPLE_SEARCH_RESULTS_FILENAME) as f: SAMPLE_SEARCH_RESULTS = yaml.safe_load(f) diff --git a/home/forms/search.py b/home/forms/search.py index 625a92ea..5b028bb0 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -70,6 +70,19 @@ def get_sort_choices(): ] +def get_classification_choices(): + return [ + ("OFFICIAL", "Official"), + ("OFFICIAL-SENSITIVE", "Official-Sensitive"), + ("SECRET", "Secret"), + ("TOP-SECRET", "Top-Secret"), + ] + + +def get_where_to_access_choices(): + return [('"Analytical Platform"', "Analytical Platform")] + + class SearchForm(forms.Form): """Django form to represent data product search page inputs""" @@ -84,11 +97,6 @@ class SearchForm(forms.Form): required=False, widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), ) - subdomains = forms.ChoiceField( - choices=get_subdomain_choices, - required=False, - widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), - ) classifications = forms.MultipleChoiceField( choices=get_classification_choices, required=False, @@ -96,8 +104,8 @@ class SearchForm(forms.Form): attrs={"class": "govuk-checkboxes__input", "form": "searchform"} ), ) - availabilities = forms.MultipleChoiceField( - choices=get_availability_choices(), + where_to_access = forms.MultipleChoiceField( + choices=get_where_to_access_choices, required=False, widget=forms.CheckboxSelectMultiple( attrs={"class": "govuk-checkboxes__input", "form": "searchform"} @@ -121,12 +129,43 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.initial["sort"] = "relevance" + def _clean_custom_property(self, custom_property: str, property_name: str): + cleaned_properties = [] + properties = self.cleaned_data.get(custom_property) + for option in properties: + cleaned_properties.append(f"{property_name}={option}") + return cleaned_properties + + def clean_classifications(self): + cleaned_classifications = self._clean_custom_property( + custom_property="classifications", property_name="sensitivityLevel" + ) + return cleaned_classifications + + def clean_where_to_access(self): + cleaned_where_to_access = self._clean_custom_property( + custom_property="where_to_access", + property_name="whereToAccessDataset", + ) + return cleaned_where_to_access + + # def encode_without_filter(self, filter_to_remove): + # """Preformat hrefs to drop individual filters""" + # # Deepcopy the cleaned data dict to avoid modifying it inplace + # query_params = deepcopy(self.cleaned_data) + + # query_params["domain"].remove(filter_to_remove) + # if len(query_params["domain"]) == 0: + # query_params.pop("domain") + + # return f"?{urlencode(query_params, doseq=True)}" + def encode_without_filter(self, filter_to_remove): """Preformat hrefs to drop individual filters""" # Deepcopy the cleaned data dict to avoid modifying it inplace query_params = deepcopy(self.cleaned_data) - if filter_to_remove == query_params.get("domains"): - query_params.pop("domains") + if filter_to_remove == query_params.get("domain"): + query_params.pop("domain") elif filter_to_remove == query_params.get("subdomains"): query_params.pop("subdomains") return f"?{urlencode(query_params, doseq=True)}" diff --git a/home/service/search.py b/home/service/search.py index 39b5f5d0..51fa9350 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -1,8 +1,9 @@ from typing import Any -from data_platform_catalogue.search_types import (MultiSelectFilter, - SingleSelectFilter, - SortOption) +from data_platform_catalogue.search_types import ( + MultiSelectFilter, + SortOption, +) from django.core.paginator import Paginator from home.forms.search import SearchForm, get_subdomain_choices @@ -10,16 +11,16 @@ from .base import GenericService -def domains_with_their_subdomains(domains: list[str]) -> list[str]: +def domain_with_their_subdomains(domain: str) -> list[str]: """ When assets are tagged to subdomains, they are not included in search results if we filter by domain alone. We need to include all possible subdomains in the filter. """ - return [ - subdomain - for domain in domains - for (subdomain, _) in get_subdomain_choices(domain) - ] + domains + domain_and_subdomains = [ + subdomain[0] for subdomain in get_subdomain_choices(domain) + ] + domain_and_subdomains.append(domain) + return domain_and_subdomains class SearchService(GenericService): @@ -36,10 +37,31 @@ def _get_search_results(self, page: str, items_per_page: int): form_data = self.form.cleaned_data else: form_data = {} + query = form_data.get("query", "") sort = form_data.get("sort", "relevance") - domains = domains_with_their_subdomains(form_data.get("domains", [])) - filter_value = [MultiSelectFilter("domains", domains)] if domains else [] + domain = form_data.get("domain") + domain = domain if domain != "Default" else "" + + classifications = form_data.get("classifications", []) + where_to_access = form_data.get("where_to_access", []) + + custom_properties = { + "classifications": classifications, + "where_to_access": where_to_access, + } + + full_query = self._query_builder(query, custom_properties) + filter_value = ( + [ + MultiSelectFilter( + filter_name="domains", + included_values=(domain_with_their_subdomains(domain=domain)), + ) + ] + if domain + else [] + ) page_for_search = str(int(page) - 1) if sort == "ascending": sort_option = SortOption(field="name", ascending=True) @@ -49,12 +71,13 @@ def _get_search_results(self, page: str, items_per_page: int): sort_option = None results = self.client.search( - query=query, + query=full_query, page=page_for_search, filters=filter_value, sort=sort_option, count=items_per_page, ) + return results def _get_paginator(self, items_per_page: int) -> Paginator: @@ -68,25 +91,24 @@ def _get_context(self) -> dict[str, Any]: else: page_title = "Search - Data catalogue" + # if self.form.is_bound: + # label_clear_href = { + # filter.split(":")[-1]: self.form.encode_without_filter(filter) + # for filter in self.form.cleaned_data.get("domain", []) + # } + # else: + # label_clear_href = None + if self.form.is_bound: label_clear_href = {} domain = self.form.cleaned_data.get("domain") - subdomain = self.form.cleaned_data.get("subdomains") if domain: - label_clear_href[ - domain.split(":")[-1] - ] = self.form.encode_without_filter( - filter_to_remove=self.form.cleaned_data.get("domain") - ) - if subdomain: - label_clear_href[ - subdomain.split(":")[-1] - ] = self.form.encode_without_filter( - filter_to_remove=self.form.cleaned_data.get("subdomains") + label_clear_href[domain.split(":")[-1]] = ( + self.form.encode_without_filter(filter_to_remove=domain) ) else: label_clear_href = None - print(label_clear_href) + # print(f"label clear ref: {label_clear_href}") context = { "form": self.form, "results": self.results.page_results, @@ -101,3 +123,19 @@ def _get_context(self) -> dict[str, Any]: } return context + + @staticmethod + def _query_builder(query: str, custom_properties: dict[str, list[str | None]]): + custom_property_query: str = "/q customProperties: " + custom_property_strings: list[str] = [] + + for _, value in custom_properties.items(): + if value: + custom_property_strings.append(" OR ".join(value)) + + if query != "": + custom_property_strings.append(query) + + final_query = " AND ".join(custom_property_strings) + + return f"{custom_property_query} {final_query}" if final_query else "*" diff --git a/home/views.py b/home/views.py index 28d02ce5..535bd831 100644 --- a/home/views.py +++ b/home/views.py @@ -24,7 +24,7 @@ def details_view(request, id): def search_view(request, page: str = "1"): - print(request.GET) + # print(request.GET) new_search = request.GET.get("new", "") if new_search: form = SearchForm() diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 6ab6f185..7aa173c3 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -18,7 +18,7 @@

Selected filters

Clear filter @@ -41,15 +41,33 @@

Domain

+
+ + {{form.domain}} + +
+
+
+ Security Classification +
+ {% for classification_option in form.classifications %} +
+ {{ classification_option.tag}} + +
+ {% endfor %} +
+
+
- Domain + Availability
- {% for domain_option in form.domains %} -
- {{ domain_option.tag}} - -
+ {% for access_option in form.where_to_access %} +
+ {{ access_option.tag}} + +
{% endfor %}
diff --git a/templates/partial/filter1.html b/templates/partial/filter1.html deleted file mode 100644 index d4940961..00000000 --- a/templates/partial/filter1.html +++ /dev/null @@ -1,84 +0,0 @@ -{% load future %} -
-
-
-
-

Filter

-
-
-
-
- -
-
-
-
-

Selected filters

-
- -
- {% if form.domains.value %} -

Domain

- - {% endif %} -
-
- -
- - {{form.domain}} - -
-
- - {{form.subdomains}} -
-
-
- Security Classification -
- {% for classification_option in form.classifications %} -
- {{ classification_option.tag}} - -
- {% endfor %} -
-
-
-
-
- Availability -
- {% for availability_option in form.availabilities %} -
- {{ availability_option.tag}} - -
- {% endfor %} -
-
-
-
-
-
-
diff --git a/templates/search.html b/templates/search.html index fbfd35eb..03436bea 100644 --- a/templates/search.html +++ b/templates/search.html @@ -24,7 +24,7 @@

Find MOJ Data

- {% include "partial/filter1.html" %} + {% include "partial/filter.html" %}

{{total_results|intcomma}} Results

{% include "partial/sort.html" %} From 95f65b5d9f3ec9be4ddb0effbf9d86ec10e939c8 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 13:48:52 +0000 Subject: [PATCH 04/60] update pre-commit - add sync_with_poetry hook to keep pre-commit in sync with pyproject.toml - config flake8 - config isort to use black via pyproject.toml Add .secrets.baseline for detect-secrets move testing libraries to dev.dependencies in pyproject.toml --- .pre-commit-config.yaml | 26 ++++- .secrets.baseline | 122 ++++++++++++++++++++++ poetry.lock | 225 +++++++++++++++++++++++++++++++++++++++- pyproject.toml | 17 +-- 4 files changed, 378 insertions(+), 12 deletions(-) create mode 100644 .secrets.baseline diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2881c581..52922b36 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,17 +11,30 @@ repos: exclude: tf$|j2$ - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 23.12.1 hooks: - id: black name: black formatting # args: [--config=./pyproject.toml] - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 name: flake8 lint + args: [ + '--ignore=E203,E266,W503,F403', + '--exclude=".git, .mypy_cache, .pytest_cache, build, dist"', + '--max-line-length=89', + '--max-complexity=18', + '--select="B,C,E,F,W,T4,B9"' + ] + additional_dependencies: + - flake8-broken-line + - flake8-bugbear + - flake8-comprehensions + - flake8-debugger + - flake8-string-format - repo: https://github.com/Yelp/detect-secrets rev: v1.4.0 @@ -31,7 +44,14 @@ repos: exclude: package.lock.json - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort name: isort (python) + additional_dependencies: ["toml"] + + - repo: https://github.com/floatingpurr/sync_with_poetry + rev: "1.1.0" + hooks: + - id: sync_with_poetry + args: [] diff --git a/.secrets.baseline b/.secrets.baseline new file mode 100644 index 00000000..47a49c0f --- /dev/null +++ b/.secrets.baseline @@ -0,0 +1,122 @@ +{ + "version": "1.4.0", + "plugins_used": [ + { + "name": "ArtifactoryDetector" + }, + { + "name": "AWSKeyDetector" + }, + { + "name": "AzureStorageKeyDetector" + }, + { + "name": "Base64HighEntropyString", + "limit": 4.5 + }, + { + "name": "BasicAuthDetector" + }, + { + "name": "CloudantDetector" + }, + { + "name": "DiscordBotTokenDetector" + }, + { + "name": "GitHubTokenDetector" + }, + { + "name": "HexHighEntropyString", + "limit": 3.0 + }, + { + "name": "IbmCloudIamDetector" + }, + { + "name": "IbmCosHmacDetector" + }, + { + "name": "JwtTokenDetector" + }, + { + "name": "KeywordDetector", + "keyword_exclude": "" + }, + { + "name": "MailchimpDetector" + }, + { + "name": "NpmDetector" + }, + { + "name": "PrivateKeyDetector" + }, + { + "name": "SendGridDetector" + }, + { + "name": "SlackDetector" + }, + { + "name": "SoftlayerDetector" + }, + { + "name": "SquareOAuthDetector" + }, + { + "name": "StripeDetector" + }, + { + "name": "TwilioKeyDetector" + } + ], + "filters_used": [ + { + "path": "detect_secrets.filters.allowlist.is_line_allowlisted" + }, + { + "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", + "min_level": 2 + }, + { + "path": "detect_secrets.filters.heuristic.is_indirect_reference" + }, + { + "path": "detect_secrets.filters.heuristic.is_likely_id_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_lock_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_potential_uuid" + }, + { + "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" + }, + { + "path": "detect_secrets.filters.heuristic.is_sequential_string" + }, + { + "path": "detect_secrets.filters.heuristic.is_swagger_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_templated_secret" + } + ], + "results": { + "templates/base/base.html": [ + { + "type": "Base64 High Entropy String", + "filename": "templates/base/base.html", + "hashed_secret": "f6538b22f89b1e2b05570de751f2932c6bca9969", + "is_verified": false, + "line_number": 40 + } + ] + }, + "generated_at": "2024-02-21T10:23:47Z" +} diff --git a/poetry.lock b/poetry.lock index d1aa58aa..cc456ba1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry and should not be changed by hand. [[package]] name = "acryl-datahub" version = "0.12.1.4" description = "A CLI to work with DataHub metadata" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -125,6 +126,7 @@ vertica = ["Deprecated", "PyYAML", "acryl-sqlglot (==20.4.1.dev14)", "aiohttp (< name = "aiohttp" version = "3.9.3" description = "Async http client/server framework (asyncio)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -220,6 +222,7 @@ speedups = ["Brotli", "aiodns", "brotlicffi"] name = "aiosignal" version = "1.3.1" description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -234,6 +237,7 @@ frozenlist = ">=1.1.0" name = "antlr4-python3-runtime" version = "4.9.2" description = "ANTLR 4.9.2 runtime for Python 3.7" +category = "main" optional = false python-versions = "*" files = [ @@ -244,6 +248,7 @@ files = [ name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" optional = false python-versions = "*" files = [ @@ -255,6 +260,7 @@ files = [ name = "asgiref" version = "3.7.2" description = "ASGI specs, helper code, and adapters" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -269,6 +275,7 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] name = "attrs" version = "23.2.0" description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -288,6 +295,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p name = "avro" version = "1.11.3" description = "Avro is a serialization and RPC framework." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -302,6 +310,7 @@ zstandard = ["zstandard"] name = "avro-gen3" version = "0.7.11" description = "Avro record class and specific record reader generator" +category = "main" optional = false python-versions = "*" files = [ @@ -317,6 +326,7 @@ six = "*" name = "beautifulsoup4" version = "4.12.3" description = "Screen-scraping library" +category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -338,6 +348,7 @@ lxml = ["lxml"] name = "black" version = "23.12.1" description = "The uncompromising code formatter." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -382,6 +393,7 @@ uvloop = ["uvloop (>=0.15.2)"] name = "boto3" version = "1.34.33" description = "The AWS SDK for Python" +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -401,6 +413,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] name = "botocore" version = "1.34.33" description = "Low-level, data-driven core of boto 3." +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -420,6 +433,7 @@ crt = ["awscrt (==0.19.19)"] name = "cached-property" version = "1.5.2" description = "A decorator for caching properties in classes." +category = "main" optional = false python-versions = "*" files = [ @@ -431,6 +445,7 @@ files = [ name = "cachetools" version = "5.3.2" description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -442,6 +457,7 @@ files = [ name = "certifi" version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -453,6 +469,7 @@ files = [ name = "cffi" version = "1.16.0" description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -517,6 +534,7 @@ pycparser = "*" name = "cfgv" version = "3.4.0" description = "Validate configuration and produce human readable error messages." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -528,6 +546,7 @@ files = [ name = "chardet" version = "4.0.0" description = "Universal encoding detector for Python 2 and 3" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -539,6 +558,7 @@ files = [ name = "charset-normalizer" version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -638,6 +658,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -652,6 +673,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "click-default-group" version = "1.2.4" description = "click_default_group" +category = "main" optional = false python-versions = ">=2.7" files = [ @@ -669,6 +691,7 @@ test = ["pytest"] name = "click-spinner" version = "0.1.10" description = "Spinner for Click" +category = "main" optional = false python-versions = "*" files = [ @@ -683,6 +706,7 @@ test = ["click", "pytest", "six"] name = "collate-sqllineage" version = "1.2.6" description = "Collate SQL Lineage for Analysis Tool powered by Python and sqlfluff based on sqllineage." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -703,6 +727,7 @@ docs = ["Sphinx (>=3.2.0)", "sphinx-rtd-theme (>=0.5.0)"] name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -714,6 +739,7 @@ files = [ name = "coverage" version = "7.4.1" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -778,6 +804,7 @@ toml = ["tomli"] name = "croniter" version = "1.3.15" description = "croniter provides iteration for datetime object with cron like format" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -792,6 +819,7 @@ python-dateutil = "*" name = "cryptography" version = "42.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -846,6 +874,7 @@ test-randomorder = ["pytest-randomly"] name = "deepdiff" version = "6.7.1" description = "Deep Difference and Search of any Python object/data. Recreate objects by adding adding deltas to each other." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -864,6 +893,7 @@ optimize = ["orjson"] name = "deprecated" version = "1.2.14" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -881,6 +911,7 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] name = "diff-cover" version = "8.0.3" description = "Run coverage and linting reports on diffs" +category = "main" optional = false python-versions = ">=3.8.10,<4.0.0" files = [ @@ -901,6 +932,7 @@ toml = ["tomli (>=1.2.1)"] name = "distlib" version = "0.3.8" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -912,6 +944,7 @@ files = [ name = "django" version = "5.0.1" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." +category = "main" optional = false python-versions = ">=3.10" files = [ @@ -932,6 +965,7 @@ bcrypt = ["bcrypt"] name = "dnspython" version = "2.5.0" description = "DNS toolkit" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -952,6 +986,7 @@ wmi = ["wmi (>=1.5.1)"] name = "docker" version = "7.0.0" description = "A Python library for the Docker Engine API." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -973,6 +1008,7 @@ websockets = ["websocket-client (>=1.3.0)"] name = "ecdsa" version = "0.18.0" description = "ECDSA cryptographic signature library (pure python)" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -991,6 +1027,7 @@ gmpy2 = ["gmpy2"] name = "email-validator" version = "2.1.0.post1" description = "A robust email address syntax and deliverability validation library." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1006,6 +1043,7 @@ idna = ">=2.0.0" name = "expandvars" version = "0.12.0" description = "Expand system variables Unix style" +category = "main" optional = false python-versions = ">=3" files = [ @@ -1020,6 +1058,7 @@ tests = ["black", "pytest", "pytest-cov", "tox"] name = "faker" version = "22.6.0" description = "Faker is a Python package that generates fake data for you." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1034,6 +1073,7 @@ python-dateutil = ">=2.4" name = "filelock" version = "3.13.1" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1046,10 +1086,28 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] +[[package]] +name = "flake8" +version = "6.1.0" +description = "the modular source code checker: pep8 pyflakes and co" +category = "dev" +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, + {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, +] + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.11.0,<2.12.0" +pyflakes = ">=3.1.0,<3.2.0" + [[package]] name = "freezegun" version = "1.4.0" description = "Let your Python tests travel through time" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1064,6 +1122,7 @@ python-dateutil = ">=2.7" name = "frozenlist" version = "1.4.1" description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1150,6 +1209,7 @@ files = [ name = "google" version = "3.0.0" description = "Python bindings to the Google search engine." +category = "main" optional = false python-versions = "*" files = [ @@ -1164,6 +1224,7 @@ beautifulsoup4 = "*" name = "google-auth" version = "2.27.0" description = "Google Authentication Library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1187,6 +1248,7 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] name = "greenlet" version = "3.0.3" description = "Lightweight in-process concurrent programming" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1258,6 +1320,7 @@ test = ["objgraph", "psutil"] name = "grpcio" version = "1.60.1" description = "HTTP/2-based RPC framework" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1324,6 +1387,7 @@ protobuf = ["grpcio-tools (>=1.60.1)"] name = "grpcio-tools" version = "1.60.1" description = "Protobuf code generator for gRPC" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1392,6 +1456,7 @@ setuptools = "*" name = "gunicorn" version = "21.2.0" description = "WSGI HTTP Server for UNIX" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1412,6 +1477,7 @@ tornado = ["tornado (>=0.2)"] name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1423,6 +1489,7 @@ files = [ name = "humanfriendly" version = "10.0" description = "Human friendly output for text interfaces using Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1437,6 +1504,7 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve name = "identify" version = "2.5.33" description = "File identification library for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1451,6 +1519,7 @@ license = ["ukkonen"] name = "idna" version = "2.10" description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1462,6 +1531,7 @@ files = [ name = "ijson" version = "3.2.3" description = "Iterative JSON parser with standard Python iterator interfaces" +category = "main" optional = false python-versions = "*" files = [ @@ -1560,6 +1630,7 @@ files = [ name = "importlib-metadata" version = "7.0.1" description = "Read metadata from Python packages" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1579,6 +1650,7 @@ testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1586,10 +1658,26 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +category = "dev" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] + [[package]] name = "jinja2" version = "3.1.3" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1607,6 +1695,7 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1618,6 +1707,7 @@ files = [ name = "jsonpatch" version = "1.32" description = "Apply JSON-Patches (RFC 6902)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1632,6 +1722,7 @@ jsonpointer = ">=1.9" name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ @@ -1643,6 +1734,7 @@ files = [ name = "jsonref" version = "1.1.0" description = "jsonref is a library for automatic dereferencing of JSON Reference objects for Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1654,6 +1746,7 @@ files = [ name = "jsonschema" version = "4.21.1" description = "An implementation of JSON Schema validation for Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1675,6 +1768,7 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "jsonschema-specifications" version = "2023.12.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1689,6 +1783,7 @@ referencing = ">=0.31.0" name = "markdown" version = "3.5.2" description = "Python implementation of John Gruber's Markdown." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1704,6 +1799,7 @@ testing = ["coverage", "pyyaml"] name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1769,10 +1865,23 @@ files = [ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + [[package]] name = "memory-profiler" version = "0.61.0" description = "A module for monitoring memory usage of a python program" +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1787,6 +1896,7 @@ psutil = "*" name = "ministryofjustice-data-platform-catalogue" version = "0.10.0" description = "Library to integrate the MoJ data platform with the catalogue component." +category = "main" optional = false python-versions = ">=3.10,<4.0" files = [ @@ -1804,6 +1914,7 @@ openmetadata-ingestion = ">=1.2.0.1,<1.3.0.0" name = "mixpanel" version = "4.10.0" description = "Official Mixpanel library for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.4.*" files = [ @@ -1820,6 +1931,7 @@ urllib3 = "*" name = "multidict" version = "6.0.5" description = "multidict implementation" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1919,6 +2031,7 @@ files = [ name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1930,6 +2043,7 @@ files = [ name = "networkx" version = "3.2.1" description = "Python package for creating and manipulating graphs and networks" +category = "main" optional = false python-versions = ">=3.9" files = [ @@ -1948,6 +2062,7 @@ test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -1962,6 +2077,7 @@ setuptools = "*" name = "openmetadata-ingestion" version = "1.2.5.1" description = "Ingestion Framework for OpenMetadata" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2073,6 +2189,7 @@ vertica = ["sqlalchemy-vertica[vertica-python] (>=0.0.5)"] name = "ordered-set" version = "4.1.0" description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2087,6 +2204,7 @@ dev = ["black", "mypy", "pytest"] name = "outcome" version = "1.3.0.post0" description = "Capture the outcome of Python function calls." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2101,6 +2219,7 @@ attrs = ">=19.2.0" name = "packaging" version = "23.2" description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2112,6 +2231,7 @@ files = [ name = "pathspec" version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2123,6 +2243,7 @@ files = [ name = "platformdirs" version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2138,6 +2259,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest- name = "pluggy" version = "1.4.0" description = "plugin and hook calling mechanisms for python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2153,6 +2275,7 @@ testing = ["pytest", "pytest-benchmark"] name = "pre-commit" version = "3.6.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." +category = "dev" optional = false python-versions = ">=3.9" files = [ @@ -2171,6 +2294,7 @@ virtualenv = ">=20.10.0" name = "progressbar2" version = "4.3.2" description = "A Python Progressbar library to provide visual (yet text based) progress to long running operations." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2189,6 +2313,7 @@ tests = ["dill (>=0.3.6)", "flake8 (>=3.7.7)", "freezegun (>=0.3.11)", "pytest ( name = "protobuf" version = "4.25.2" description = "" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2209,6 +2334,7 @@ files = [ name = "psutil" version = "5.9.8" description = "Cross-platform lib for process and system monitoring in Python." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -2237,6 +2363,7 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] name = "pyasn1" version = "0.5.1" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2248,6 +2375,7 @@ files = [ name = "pyasn1-modules" version = "0.3.0" description = "A collection of ASN.1-based protocols modules" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2258,10 +2386,23 @@ files = [ [package.dependencies] pyasn1 = ">=0.4.6,<0.6.0" +[[package]] +name = "pycodestyle" +version = "2.11.1" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, + {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, +] + [[package]] name = "pycparser" version = "2.21" description = "C parser in Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2273,6 +2414,7 @@ files = [ name = "pydantic" version = "1.10.14" description = "Data validation and settings management using python type hints" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2321,10 +2463,23 @@ typing-extensions = ">=4.2.0" dotenv = ["python-dotenv (>=0.10.4)"] email = ["email-validator (>=1.0.3)"] +[[package]] +name = "pyflakes" +version = "3.1.0" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, + {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, +] + [[package]] name = "pygments" version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2340,6 +2495,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pymysql" version = "1.1.0" description = "Pure Python MySQL Driver" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2351,10 +2507,26 @@ files = [ ed25519 = ["PyNaCl (>=1.4.0)"] rsa = ["cryptography"] +[[package]] +name = "pyproject-flake8" +version = "6.1.0" +description = "pyproject-flake8 (`pflake8`), a monkey patching wrapper to connect flake8 with pyproject.toml configuration" +category = "dev" +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "pyproject_flake8-6.1.0-py3-none-any.whl", hash = "sha256:86ea5559263c098e1aa4f866776aa2cf45362fd91a576b9fd8fbbbb55db12c4e"}, + {file = "pyproject_flake8-6.1.0.tar.gz", hash = "sha256:6da8e5a264395e0148bc11844c6fb50546f1fac83ac9210f7328664135f9e70f"}, +] + +[package.dependencies] +flake8 = "6.1.0" + [[package]] name = "pyreadline3" version = "3.4.1" description = "A python implementation of GNU readline." +category = "main" optional = false python-versions = "*" files = [ @@ -2366,6 +2538,7 @@ files = [ name = "pysocks" version = "1.7.1" description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2378,6 +2551,7 @@ files = [ name = "pytest" version = "8.0.0" description = "pytest: simple powerful testing with Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2398,6 +2572,7 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-cov" version = "4.1.0" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2416,6 +2591,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-django" version = "4.8.0" description = "A Django plugin for pytest." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2434,6 +2610,7 @@ testing = ["Django", "django-configurations (>=2.0)"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -2448,6 +2625,7 @@ six = ">=1.5" name = "python-dotenv" version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2462,6 +2640,7 @@ cli = ["click (>=5.0)"] name = "python-jose" version = "3.3.0" description = "JOSE implementation in Python" +category = "main" optional = false python-versions = "*" files = [ @@ -2483,6 +2662,7 @@ pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] name = "python-utils" version = "3.8.2" description = "Python Utils is a module with some convenient utilities not included with the standard Python install" +category = "main" optional = false python-versions = ">3.8.0" files = [ @@ -2502,6 +2682,7 @@ tests = ["flake8", "loguru", "pytest", "pytest-asyncio", "pytest-cov", "pytest-m name = "pywin32" version = "306" description = "Python for Window Extensions" +category = "main" optional = false python-versions = "*" files = [ @@ -2525,6 +2706,7 @@ files = [ name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2584,6 +2766,7 @@ files = [ name = "referencing" version = "0.33.0" description = "JSON Referencing + Python" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2599,6 +2782,7 @@ rpds-py = ">=0.7.0" name = "regex" version = "2023.12.25" description = "Alternative regular expression module, to replace re." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2701,6 +2885,7 @@ files = [ name = "requests" version = "2.31.0" description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2722,6 +2907,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-aws4auth" version = "1.2.3" description = "AWS4 authentication for Requests" +category = "main" optional = false python-versions = ">=3.3" files = [ @@ -2740,6 +2926,7 @@ httpx = ["httpx"] name = "requests-file" version = "2.0.0" description = "File transport adapter for Requests" +category = "main" optional = false python-versions = "*" files = [ @@ -2754,6 +2941,7 @@ requests = ">=1.0.0" name = "rpds-py" version = "0.17.1" description = "Python bindings to Rust's persistent data structures (rpds)" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2862,6 +3050,7 @@ files = [ name = "rsa" version = "4.9" description = "Pure-Python RSA implementation" +category = "main" optional = false python-versions = ">=3.6,<4" files = [ @@ -2876,6 +3065,7 @@ pyasn1 = ">=0.1.3" name = "ruamel-yaml" version = "0.18.5" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2894,6 +3084,7 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] name = "ruamel-yaml-clib" version = "0.2.8" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2953,6 +3144,7 @@ files = [ name = "s3transfer" version = "0.10.0" description = "An Amazon S3 Transfer Manager" +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -2970,6 +3162,7 @@ crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] name = "selenium" version = "4.17.2" description = "" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -2988,6 +3181,7 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]} name = "sentry-sdk" version = "1.40.0" description = "Python client for Sentry (https://sentry.io)" +category = "main" optional = false python-versions = "*" files = [ @@ -3033,6 +3227,7 @@ tornado = ["tornado (>=5)"] name = "setuptools" version = "66.0.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3049,6 +3244,7 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs ( name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3060,6 +3256,7 @@ files = [ name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3071,6 +3268,7 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "dev" optional = false python-versions = "*" files = [ @@ -3082,6 +3280,7 @@ files = [ name = "soupsieve" version = "2.5" description = "A modern CSS selector implementation for Beautiful Soup." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3093,6 +3292,7 @@ files = [ name = "sqlalchemy" version = "1.4.51" description = "Database Abstraction Library" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -3172,6 +3372,7 @@ sqlcipher = ["sqlcipher3_binary"] name = "sqlfluff" version = "2.3.5" description = "The SQL Linter for Humans" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3198,6 +3399,7 @@ typing-extensions = "*" name = "sqlparse" version = "0.4.4" description = "A non-validating SQL parser." +category = "main" optional = false python-versions = ">=3.5" files = [ @@ -3214,6 +3416,7 @@ test = ["pytest", "pytest-cov"] name = "tabulate" version = "0.9.0" description = "Pretty-print tabular data" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3228,6 +3431,7 @@ widechars = ["wcwidth"] name = "tblib" version = "3.0.0" description = "Traceback serialization library." +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3239,6 +3443,7 @@ files = [ name = "termcolor" version = "2.4.0" description = "ANSI color formatting for output in terminal" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3253,6 +3458,7 @@ tests = ["pytest", "pytest-cov"] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -3264,6 +3470,7 @@ files = [ name = "tqdm" version = "4.66.1" description = "Fast, Extensible Progress Meter" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3284,6 +3491,7 @@ telegram = ["requests"] name = "trio" version = "0.24.0" description = "A friendly Python library for async concurrency and I/O" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -3303,6 +3511,7 @@ sortedcontainers = "*" name = "trio-websocket" version = "0.11.1" description = "WebSocket library for Trio" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3318,6 +3527,7 @@ wsproto = ">=0.14" name = "typing-compat" version = "0.1.0" description = "Python typing compatibility library" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -3329,6 +3539,7 @@ files = [ name = "typing-extensions" version = "4.9.0" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3340,6 +3551,7 @@ files = [ name = "typing-inspect" version = "0.9.0" description = "Runtime inspection utilities for typing module." +category = "main" optional = false python-versions = "*" files = [ @@ -3355,6 +3567,7 @@ typing-extensions = ">=3.7.4" name = "tzdata" version = "2023.4" description = "Provider of IANA time zone data" +category = "main" optional = false python-versions = ">=2" files = [ @@ -3366,6 +3579,7 @@ files = [ name = "urllib3" version = "2.0.7" description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3386,6 +3600,7 @@ zstd = ["zstandard (>=0.18.0)"] name = "virtualenv" version = "20.25.0" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3406,6 +3621,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "wheel" version = "0.38.4" description = "A built-package format for Python" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3420,6 +3636,7 @@ test = ["pytest (>=3.0.0)"] name = "whitenoise" version = "6.6.0" description = "Radically simplified static file serving for WSGI applications" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3434,6 +3651,7 @@ brotli = ["Brotli"] name = "wrapt" version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3513,6 +3731,7 @@ files = [ name = "wsproto" version = "1.2.0" description = "WebSockets state-machine based protocol implementation" +category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -3527,6 +3746,7 @@ h11 = ">=0.9.0,<1" name = "yarl" version = "1.9.4" description = "Yet another URL library" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3630,6 +3850,7 @@ multidict = ">=4.0" name = "zipp" version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3644,4 +3865,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "5cd66d8abbeaa1b06f98ce3820d1c076aed4aa1606f435184323085384cec037" +content-hash = "a6499263725090cc0407852e9223b24a8c10269b11d75af9cdcbcf962809c7bb" diff --git a/pyproject.toml b/pyproject.toml index 1c91a552..b47e9f3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,17 +14,17 @@ whitenoise = "^6.6.0" ministryofjustice-data-platform-catalogue = "^0.10.0" markdown = "^3.5.2" python-dotenv = "^1.0.1" -faker = "^22.6.0" -selenium = "^4.17.2" -pytest-django = "^4.8.0" -pytest-cov = "^4.1.0" - -[tool.poetry.group.dev] # dev group definition [tool.poetry.group.dev.dependencies] black = "^23.12.1" pre-commit = "^3.6.0" -selenium = ">=4.8.0" +selenium = "^4.17.2" +flake8 = ">=6.1.0" +pytest-django = "^4.8.0" +pytest-cov = "^4.1.0" +faker = "^22.6.0" +isort = "^5.13.2" +pyproject-flake8 = "^6.1.0" [build-system] requires = ["poetry-core"] @@ -34,3 +34,6 @@ build-backend = "poetry.core.masonry.api" DJANGO_SETTINGS_MODULE = "core.settings" python_files = ["test_*.py", "*_test.py", "testing/python/*.py"] markers = ["slow: marks tests as slow (deselect with '-m \"not slow\"')"] + +[tool.isort] +profile = "black" From ccdebcb79aa851e17f3b8b34025a51df476937e2 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 13:55:37 +0000 Subject: [PATCH 05/60] linting --- core/__init__.py | 2 +- core/settings.py | 2 +- core/urls.py | 1 + home/admin.py | 2 +- home/forms/search.py | 2 +- home/service/details.py | 3 +-- home/service/search.py | 5 +---- home/tests.py | 2 +- home/urls.py | 1 + home/views.py | 2 +- templates/base/base.html | 2 +- templates/base/error/page_not_found.html | 2 +- templates/base/head.html | 2 +- templates/details.html | 24 ++++++++++++------------ templates/home.html | 1 - templates/partial/search_result.html | 4 ++-- tests/conftest.py | 6 ++---- tests/selenium/conftest.py | 4 +--- tests/test_services.py | 7 ++++++- 19 files changed, 36 insertions(+), 38 deletions(-) diff --git a/core/__init__.py b/core/__init__.py index a39da083..46a080bc 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -from .settings import * +from .settings import * # noqa: F401 diff --git a/core/settings.py b/core/settings.py index e906359d..3d84b3ca 100644 --- a/core/settings.py +++ b/core/settings.py @@ -67,7 +67,7 @@ AUTH_PASSWORD_VALIDATORS = [ { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", # noqa: E501 }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", diff --git a/core/urls.py b/core/urls.py index 796075bf..b04e5a6f 100644 --- a/core/urls.py +++ b/core/urls.py @@ -14,6 +14,7 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ + from django.contrib import admin from django.urls import include, path diff --git a/home/admin.py b/home/admin.py index 8c38f3f3..4185d360 100644 --- a/home/admin.py +++ b/home/admin.py @@ -1,3 +1,3 @@ -from django.contrib import admin +# from django.contrib import admin # Register your models here. diff --git a/home/forms/search.py b/home/forms/search.py index 5b028bb0..ccf6aa51 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -4,7 +4,7 @@ from django import forms -def get_domain_choices(): +def get_domain_choices() -> list[tuple[str, str]]: """Make API call to obtain domain choices""" # TODO: pull in the domains from the catalogue client # facets = client.search_facets() diff --git a/home/service/details.py b/home/service/details.py index da87f7f8..903eb8ce 100644 --- a/home/service/details.py +++ b/home/service/details.py @@ -10,8 +10,7 @@ def __init__(self, urn: str): self.client = self._get_catalogue_client() filter_value = [MultiSelectFilter("urn", [urn])] - search_results = self.client.search( - query="", page=None, filters=filter_value) + search_results = self.client.search(query="", page=None, filters=filter_value) if not search_results.page_results: raise ObjectDoesNotExist(urn) diff --git a/home/service/search.py b/home/service/search.py index 51fa9350..5255a735 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -1,9 +1,6 @@ from typing import Any -from data_platform_catalogue.search_types import ( - MultiSelectFilter, - SortOption, -) +from data_platform_catalogue.search_types import MultiSelectFilter, SortOption from django.core.paginator import Paginator from home.forms.search import SearchForm, get_subdomain_choices diff --git a/home/tests.py b/home/tests.py index 7ce503c2..a79ca8be 100644 --- a/home/tests.py +++ b/home/tests.py @@ -1,3 +1,3 @@ -from django.test import TestCase +# from django.test import TestCase # Create your tests here. diff --git a/home/urls.py b/home/urls.py index d508c4f4..c9ec0a16 100644 --- a/home/urls.py +++ b/home/urls.py @@ -1,4 +1,5 @@ from django.urls import path + from . import views app_name = "home" diff --git a/home/views.py b/home/views.py index 535bd831..29b35e48 100644 --- a/home/views.py +++ b/home/views.py @@ -1,4 +1,4 @@ -from django.core.exceptions import ObjectDoesNotExist, ValidationError +from django.core.exceptions import ObjectDoesNotExist from django.http import Http404, HttpResponseBadRequest from django.shortcuts import render diff --git a/templates/base/base.html b/templates/base/base.html index 70a587e6..ff0fefb9 100644 --- a/templates/base/base.html +++ b/templates/base/base.html @@ -46,4 +46,4 @@ window.MOJFrontend.initAll(); - \ No newline at end of file + diff --git a/templates/base/error/page_not_found.html b/templates/base/error/page_not_found.html index 9e8db9b9..45d239e9 100644 --- a/templates/base/error/page_not_found.html +++ b/templates/base/error/page_not_found.html @@ -15,4 +15,4 @@

Page not found

-
\ No newline at end of file +
diff --git a/templates/base/head.html b/templates/base/head.html index 452857ef..da3dfed9 100644 --- a/templates/base/head.html +++ b/templates/base/head.html @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/templates/details.html b/templates/details.html index 3367bad3..001e81d8 100644 --- a/templates/details.html +++ b/templates/details.html @@ -8,7 +8,7 @@ Back
-
+
{{result_type}}

{{result.name}}

@@ -28,16 +28,16 @@

{{result.name}}

{{result.metadata.owner_email}}
- - + +
Domain name
{{result.metadata.domain.properties.name}}
- - + +
Last updated date
@@ -46,24 +46,24 @@

{{result.name}}

{% endif %}
- +
Refresh period
- +
- +
Retention period
- +
DPIA Status
- +
@@ -109,7 +109,7 @@

{{result.name}}

- +

IAO or Data Owner

@@ -126,7 +126,7 @@

{{result.name}}

Access requirement

- Processing the data might require + Processing the data might require permission from IAO or Data owner
diff --git a/templates/home.html b/templates/home.html index 0bb8fb40..ba8879e8 100644 --- a/templates/home.html +++ b/templates/home.html @@ -6,5 +6,4 @@ Back

Customised page template

- {% endblock content %} diff --git a/templates/partial/search_result.html b/templates/partial/search_result.html index 1a409614..35ae4d8b 100644 --- a/templates/partial/search_result.html +++ b/templates/partial/search_result.html @@ -21,7 +21,7 @@

{{result.metadata.search_summary|markdown}}
{% endif %} - +
@@ -53,4 +53,4 @@

{%endfor%} -
\ No newline at end of file +
diff --git a/tests/conftest.py b/tests/conftest.py index 68c34893..4241f355 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -29,8 +29,7 @@ def generate_page(page_size=20): results.append( SearchResult( id=fake.unique.name(), - result_type=choice( - (ResultType.DATA_PRODUCT, ResultType.TABLE)), + result_type=choice((ResultType.DATA_PRODUCT, ResultType.TABLE)), name=fake.name(), description=fake.paragraphs(), ) @@ -84,8 +83,7 @@ def mock_search_response(mock_catalogue, total_results=0, page_results=()): def mock_search_facets_response(mock_catalogue, domains): - mock_catalogue.search_facets.return_value = SearchFacets( - {"domains": domains}) + mock_catalogue.search_facets.return_value = SearchFacets({"domains": domains}) @pytest.fixture diff --git a/tests/selenium/conftest.py b/tests/selenium/conftest.py index 13e03dab..35c5c636 100644 --- a/tests/selenium/conftest.py +++ b/tests/selenium/conftest.py @@ -1,9 +1,9 @@ -from pytest import CollectReport, StashKey import datetime from pathlib import Path from typing import Any, Generator import pytest +from pytest import CollectReport, StashKey from selenium.webdriver import ChromeOptions from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.by import By @@ -72,7 +72,6 @@ def secondary_heading(self): class HomePage(Page): - def search_nav_link(self) -> WebElement: return self.selenium.find_element(By.LINK_TEXT, "Search") @@ -89,7 +88,6 @@ def link(self): class SearchPage(Page): - def primary_heading(self): return self.selenium.find_element(By.TAG_NAME, "h1") diff --git a/tests/test_services.py b/tests/test_services.py index f4392336..5929d43b 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -24,7 +24,12 @@ def test_get_context_page_title(self, search_context): def test_get_context_label_clear_href(self, search_context): assert search_context["label_clear_href"] == { - "HMCTS": "?query=test&sort=ascending&clear_filter=False&clear_label=False" + "HMCTS": ( + "?query=test&" + "sort=ascending&" + "clear_filter=False&" + "clear_label=False" + ) } From a1fb16816e1ede1249c652c8634908eb6b4e4012 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 16:04:05 +0000 Subject: [PATCH 06/60] linting and formatting for readability --- tests/test_forms.py | 14 ++++++++------ tests/test_views.py | 1 - 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/test_forms.py b/tests/test_forms.py index 89fb5d91..56a96043 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -16,9 +16,8 @@ def test_all_fields_nullable(self): assert SearchForm(data={}).is_valid() def test_form_encode_without_filter_for_one_filter(self, valid_form): - assert ( - valid_form.encode_without_filter("urn:li:domain:HMCTS") - == "?query=test&sort=ascending&clear_filter=False&clear_label=False" + assert valid_form.encode_without_filter("urn:li:domain:HMCTS") == ( + "?query=test&" "sort=ascending&" "clear_filter=False&" "clear_label=False" ) def test_form_encode_without_filter_for_two_filters(self): @@ -30,7 +29,10 @@ def test_form_encode_without_filter_for_two_filters(self): ) two_filter_form.is_valid() - assert ( - two_filter_form.encode_without_filter("urn:li:domain:HMCTS") - == "?query=test&domains=urn%3Ali%3Adomain%3AHMPPS&sort=&clear_filter=False&clear_label=False" + assert two_filter_form.encode_without_filter("urn:li:domain:HMCTS") == ( + "?query=test&" + "domain=urn%3Ali%3Adomain%3AHMPPS&" + "sort=&" + "clear_filter=False&" + "clear_label=False" ) diff --git a/tests/test_views.py b/tests/test_views.py index 1f46c9ba..0c6e7abf 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,4 +1,3 @@ - from data_platform_catalogue.search_types import SearchResponse from django.urls import reverse From 1079046d0079f61bc95ff6aec6ca48bae40d3745 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 16:27:19 +0000 Subject: [PATCH 07/60] revert domains (plural) -> domain (singular) changes (may be implemented in later PR) --- home/forms/search.py | 20 ++++------------ home/service/search.py | 44 ++++++++++------------------------- templates/partial/filter.html | 14 ++++++++--- tests/test_forms.py | 2 +- 4 files changed, 28 insertions(+), 52 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index ccf6aa51..54838871 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -92,7 +92,7 @@ class SearchForm(forms.Form): required=False, widget=forms.TextInput(attrs={"class": "govuk-input search-input"}), ) - domain = forms.ChoiceField( + domains = forms.MultipleChoiceField( choices=get_domain_choices, required=False, widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), @@ -149,23 +149,11 @@ def clean_where_to_access(self): ) return cleaned_where_to_access - # def encode_without_filter(self, filter_to_remove): - # """Preformat hrefs to drop individual filters""" - # # Deepcopy the cleaned data dict to avoid modifying it inplace - # query_params = deepcopy(self.cleaned_data) - - # query_params["domain"].remove(filter_to_remove) - # if len(query_params["domain"]) == 0: - # query_params.pop("domain") - - # return f"?{urlencode(query_params, doseq=True)}" - def encode_without_filter(self, filter_to_remove): """Preformat hrefs to drop individual filters""" # Deepcopy the cleaned data dict to avoid modifying it inplace query_params = deepcopy(self.cleaned_data) - if filter_to_remove == query_params.get("domain"): - query_params.pop("domain") - elif filter_to_remove == query_params.get("subdomains"): - query_params.pop("subdomains") + query_params["domains"].remove(filter_to_remove) + if len(query_params["domains"]) == 0: + query_params.pop("domains") return f"?{urlencode(query_params, doseq=True)}" diff --git a/home/service/search.py b/home/service/search.py index 5255a735..c4335a24 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -8,16 +8,16 @@ from .base import GenericService -def domain_with_their_subdomains(domain: str) -> list[str]: +def domains_with_their_subdomains(domains: list[str]) -> list[str]: """ When assets are tagged to subdomains, they are not included in search results if we filter by domain alone. We need to include all possible subdomains in the filter. """ - domain_and_subdomains = [ - subdomain[0] for subdomain in get_subdomain_choices(domain) - ] - domain_and_subdomains.append(domain) - return domain_and_subdomains + return [ + subdomain + for domain in domains + for (subdomain, _) in get_subdomain_choices(domain) + ] + domains class SearchService(GenericService): @@ -37,8 +37,8 @@ def _get_search_results(self, page: str, items_per_page: int): query = form_data.get("query", "") sort = form_data.get("sort", "relevance") - domain = form_data.get("domain") - domain = domain if domain != "Default" else "" + domains = domains_with_their_subdomains(form_data.get("domains", [])) + filter_value = [MultiSelectFilter("domains", domains)] if domains else [] classifications = form_data.get("classifications", []) where_to_access = form_data.get("where_to_access", []) @@ -49,16 +49,6 @@ def _get_search_results(self, page: str, items_per_page: int): } full_query = self._query_builder(query, custom_properties) - filter_value = ( - [ - MultiSelectFilter( - filter_name="domains", - included_values=(domain_with_their_subdomains(domain=domain)), - ) - ] - if domain - else [] - ) page_for_search = str(int(page) - 1) if sort == "ascending": sort_option = SortOption(field="name", ascending=True) @@ -88,21 +78,11 @@ def _get_context(self) -> dict[str, Any]: else: page_title = "Search - Data catalogue" - # if self.form.is_bound: - # label_clear_href = { - # filter.split(":")[-1]: self.form.encode_without_filter(filter) - # for filter in self.form.cleaned_data.get("domain", []) - # } - # else: - # label_clear_href = None - if self.form.is_bound: - label_clear_href = {} - domain = self.form.cleaned_data.get("domain") - if domain: - label_clear_href[domain.split(":")[-1]] = ( - self.form.encode_without_filter(filter_to_remove=domain) - ) + label_clear_href = { + filter.split(":")[-1]: self.form.encode_without_filter(filter) + for filter in self.form.cleaned_data.get("domains", []) + } else: label_clear_href = None # print(f"label clear ref: {label_clear_href}") diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 7aa173c3..6e802acc 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -42,9 +42,17 @@

Domain

Apply filters
- - {{form.domain}} - +
+ Domain +
+ {% for domain_option in form.domains %} +
+ {{ domain_option.tag}} + +
+ {% endfor %} +
+
diff --git a/tests/test_forms.py b/tests/test_forms.py index 56a96043..3fd173bc 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -31,7 +31,7 @@ def test_form_encode_without_filter_for_two_filters(self): assert two_filter_form.encode_without_filter("urn:li:domain:HMCTS") == ( "?query=test&" - "domain=urn%3Ali%3Adomain%3AHMPPS&" + "domains=urn%3Ali%3Adomain%3AHMPPS&" "sort=&" "clear_filter=False&" "clear_label=False" From 2e78f6d9149b69b5bae80540943caa0e3a617ad0 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 16:28:23 +0000 Subject: [PATCH 08/60] add descriptions and code annotations for added helper functions add default for dict.get() [linting] --- home/forms/search.py | 19 +++++++++++++++++-- home/service/search.py | 20 ++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index 54838871..6a140269 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -129,9 +129,24 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.initial["sort"] = "relevance" - def _clean_custom_property(self, custom_property: str, property_name: str): + def _clean_custom_property( + self, custom_property: str, property_name: str + ) -> list[str]: + """Helper function to style DataHub customProperties into their search syntax + (customPropertyName="custom property"). Reformats the 'cleaned_data' list for a + property. + + ref: https://datahubproject.io/docs/how/search/#advanced-queries + + Args: + custom_property (str): Name of the custom property object in this codebase + property_name (str): Name of the custom property in DataHub + + Returns: + list[str]: List of reformatted custom properties. + """ cleaned_properties = [] - properties = self.cleaned_data.get(custom_property) + properties = self.cleaned_data.get(custom_property, []) for option in properties: cleaned_properties.append(f"{property_name}={option}") return cleaned_properties diff --git a/home/service/search.py b/home/service/search.py index c4335a24..5e676fff 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -102,17 +102,33 @@ def _get_context(self) -> dict[str, Any]: return context @staticmethod - def _query_builder(query: str, custom_properties: dict[str, list[str | None]]): + def _query_builder(query: str, custom_properties: dict[str, list[str]]) -> str: + """Construct a valid DataHub search query using the input query and the passed + customProperties. + + Args: + query (str): User search string + custom_properties (dict[str, list[str | None]]): Dictionary of custom + property name and custom property values selected to filter on. + + Returns: + str: advanced query string to pass to DataHub that will include 'filtering' + logic for custom properties + """ + # ref: https://datahubproject.io/docs/how/search/#advanced-queries custom_property_query: str = "/q customProperties: " custom_property_strings: list[str] = [] for _, value in custom_properties.items(): if value: - custom_property_strings.append(" OR ".join(value)) + # within-filter options are inclusive OR + custom_property_string = " OR ".join(value) + custom_property_strings.append(custom_property_string) if query != "": custom_property_strings.append(query) + # cross-filter options are exclusive AND final_query = " AND ".join(custom_property_strings) return f"{custom_property_query} {final_query}" if final_query else "*" From c8d5d6f55a05f381eba30acbf2f816f792091676 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 16:57:06 +0000 Subject: [PATCH 09/60] keep original indent for domain filters --- templates/partial/filter.html | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 6e802acc..76234180 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -42,17 +42,17 @@

Domain

Apply filters
-
- Domain -
- {% for domain_option in form.domains %} -
- {{ domain_option.tag}} - -
- {% endfor %} -
-
+
+ Domain +
+ {% for domain_option in form.domains %} +
+ {{ domain_option.tag}} + +
+ {% endfor %} +
+
From 9f352500d99bed1b29cc58df86fb39116c4f11e0 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 16:58:14 +0000 Subject: [PATCH 10/60] linting --- tests/test_views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_views.py b/tests/test_views.py index 0c6e7abf..cf13a1d5 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -34,8 +34,7 @@ def test_bad_form(self, client): class TestDetailsView: def test_details(self, client): response = client.get( - reverse("home:details", kwargs={ - "id": "urn:li:dataProduct:common-platform"}) + reverse("home:details", kwargs={"id": "urn:li:dataProduct:common-platform"}) ) assert response.status_code == 200 From 8a181a9dd53bd14dbb561d216dcf514236f4236a Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Thu, 22 Feb 2024 11:01:54 +0000 Subject: [PATCH 11/60] add pre-commit instructions/details to readme --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 464262ab..552f5c7d 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ You will need npm (for javascript dependencies) and poetry (for python dependenc 1. Run `poetry install` to install python dependencies 2. Copy `.env.example` to `.env`. -3. You wil need to obtain an access token from Datahub catalogue and populate the `CATALOGUE_TOKEN` var in .env to be able to retrieve search data. - https://datahub.apps-tools.development.data-platform.service.justice.gov.uk/settings/tokens +3. You wil need to obtain an access token from Datahub catalogue and populate the +`CATALOGUE_TOKEN` var in .env to be able to retrieve search data. 4. Run `poetry run python manage.py runserver` Run `npm install` and then `npm run sass` to compile the stylesheets. @@ -16,6 +16,16 @@ Run `npm install` and then `npm run sass` to compile the stylesheets. ![Screenshot of the service showing the search page](image.png) +## Contributing + +Run `pre-commit install` from inside the poetry environment to set up pre commit hooks. + +- Linting and formatting handled by `black`, `flake8`, `pre-commit`, and `isort` + - `isort` is configured in `pyproject.toml` +- `detect-secrets` is used to prevent leakage of secrets +- `sync_with_poetry` ensures the versions of the modules in the pre-commit specification + are kept in line with those in the `pyproject.toml` config. + ## Testing - Unit tests: `pytest -m 'not slow'` From a46b1c697d48e571a3200a9d0e5f49357b8a00f8 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Thu, 22 Feb 2024 14:38:30 +0000 Subject: [PATCH 12/60] =?UTF-8?q?Changed=20value=20for=20selection=20optio?= =?UTF-8?q?n=20an=20empty=20string=20and=20updated=20where=5Fto=5Faccess?= =?UTF-8?q?=20choice=20value=20to=20'Analytical=5FPlatform'=20to=20avoid?= =?UTF-8?q?=20spaces.=20q=20exit=20quit()=20q=20=16=1B[200~classifications?= =?UTF-8?q?~classifications?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- home/forms/search.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index 6a140269..62f2af91 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -10,7 +10,7 @@ def get_domain_choices() -> list[tuple[str, str]]: # facets = client.search_facets() # domain_list = facets.options("domains") return [ - ("Default", "Select ..."), + ("", "Select ..."), ("urn:li:domain:HMCTS", "HMCTS"), ("urn:li:domain:HMPPS", "HMPPS"), ("urn:li:domain:HQ", "HQ"), @@ -80,7 +80,7 @@ def get_classification_choices(): def get_where_to_access_choices(): - return [('"Analytical Platform"', "Analytical Platform")] + return [("Analytical_Platform", "Analytical Platform")] class SearchForm(forms.Form): From 389a609ad96810d311e03799c26c984e9d5d6e25 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Thu, 22 Feb 2024 14:42:47 +0000 Subject: [PATCH 13/60] Make domain a single choice field --- home/forms/search.py | 11 +++++---- home/service/search.py | 38 ++++++++++++++++++++----------- home/templatetags/clear_filter.py | 15 ++++++++++++ home/views.py | 1 - templates/partial/filter.html | 27 ++++++++++++++-------- 5 files changed, 64 insertions(+), 28 deletions(-) create mode 100644 home/templatetags/clear_filter.py diff --git a/home/forms/search.py b/home/forms/search.py index 62f2af91..cfe95434 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -92,7 +92,7 @@ class SearchForm(forms.Form): required=False, widget=forms.TextInput(attrs={"class": "govuk-input search-input"}), ) - domains = forms.MultipleChoiceField( + domain = forms.ChoiceField( choices=get_domain_choices, required=False, widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), @@ -168,7 +168,10 @@ def encode_without_filter(self, filter_to_remove): """Preformat hrefs to drop individual filters""" # Deepcopy the cleaned data dict to avoid modifying it inplace query_params = deepcopy(self.cleaned_data) - query_params["domains"].remove(filter_to_remove) - if len(query_params["domains"]) == 0: - query_params.pop("domains") + domain = query_params.get("domain") + classifications = query_params.get("classifications") + if domain == filter_to_remove: + query_params.pop("domain") + elif filter_to_remove in classifications: + query_params["classifications"].remove(filter_to_remove) return f"?{urlencode(query_params, doseq=True)}" diff --git a/home/service/search.py b/home/service/search.py index 5e676fff..234e6a2c 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -8,16 +8,13 @@ from .base import GenericService -def domains_with_their_subdomains(domains: list[str]) -> list[str]: +def domains_with_their_subdomains(domain: str) -> list[str]: """ When assets are tagged to subdomains, they are not included in search results if we filter by domain alone. We need to include all possible subdomains in the filter. """ - return [ - subdomain - for domain in domains - for (subdomain, _) in get_subdomain_choices(domain) - ] + domains + subdomains = get_subdomain_choices(domain) + return [domain, *subdomains] if subdomains else subdomains class SearchService(GenericService): @@ -37,8 +34,13 @@ def _get_search_results(self, page: str, items_per_page: int): query = form_data.get("query", "") sort = form_data.get("sort", "relevance") - domains = domains_with_their_subdomains(form_data.get("domains", [])) - filter_value = [MultiSelectFilter("domains", domains)] if domains else [] + domain = form_data.get("domain", "") + domains_and_subdomains = domains_with_their_subdomains(domain) + filter_value = ( + [MultiSelectFilter("domains", domains_and_subdomains)] + if domains_and_subdomains + else [] + ) classifications = form_data.get("classifications", []) where_to_access = form_data.get("where_to_access", []) @@ -79,13 +81,23 @@ def _get_context(self) -> dict[str, Any]: page_title = "Search - Data catalogue" if self.form.is_bound: - label_clear_href = { - filter.split(":")[-1]: self.form.encode_without_filter(filter) - for filter in self.form.cleaned_data.get("domains", []) - } + domain = self.form.cleaned_data.get("domain", "") + classifications = self.form.cleaned_data.get("classifications", []) + label_clear_href = {} + if domain: + label_clear_href["domain"] = { + domain.split(":")[-1]: (self.form.encode_without_filter(domain)) + } + if classifications: + classifications_clear_href = {} + for classification in classifications: + classifications_clear_href[ + classification.split("=")[1] + ] = self.form.encode_without_filter(classification) + label_clear_href["classifications"] = classifications_clear_href else: label_clear_href = None - # print(f"label clear ref: {label_clear_href}") + print(f"label clear ref: {label_clear_href}") context = { "form": self.form, "results": self.results.page_results, diff --git a/home/templatetags/clear_filter.py b/home/templatetags/clear_filter.py new file mode 100644 index 00000000..b8538909 --- /dev/null +++ b/home/templatetags/clear_filter.py @@ -0,0 +1,15 @@ +from django import template + +register = template.Library() + + +@register.filter +def get_item(dictionary, key): + print(key) + print(dictionary) + return dictionary.get(key) + + +@register.filter +def get_items(dictionary, key): + return dictionary.get(key).items() diff --git a/home/views.py b/home/views.py index 29b35e48..b7160dfd 100644 --- a/home/views.py +++ b/home/views.py @@ -24,7 +24,6 @@ def details_view(request, id): def search_view(request, page: str = "1"): - # print(request.GET) new_search = request.GET.get("new", "") if new_search: form = SearchForm() diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 76234180..83ec7b2d 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -1,4 +1,5 @@ {% load future %} +{% load clear_filter %}
@@ -18,18 +19,29 @@

Selected filters

- {% if form.domains.value %} + {% if label_clear_href|get_item:"domain"|length > 0 %}

Domain

+ {% endif %} + {% if label_clear_href|get_item:"classifications"|length > 0 %} +

Security Classifications

+
    + + {% for label, href in label_clear_href|get_items:"classifications" %}
  • {{label}} Remove this filter
  • @@ -45,12 +57,7 @@

    Domain

    Domain
    - {% for domain_option in form.domains %} -
    - {{ domain_option.tag}} - -
    - {% endfor %} + {{form.domain}}
@@ -74,7 +81,7 @@

Domain

{% for access_option in form.where_to_access %}
{{ access_option.tag}} - +
{% endfor %}
From 4de3eb358855924222c072cb06e59293825be873 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 20:58:42 +0000 Subject: [PATCH 14/60] Removed admin.py as not required --- home/admin.py | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 home/admin.py diff --git a/home/admin.py b/home/admin.py deleted file mode 100644 index 4185d360..00000000 --- a/home/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -# from django.contrib import admin - -# Register your models here. From 90c43688e8be5c820953210dfb9624975606f26b Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 20:59:41 +0000 Subject: [PATCH 15/60] Moved filter code to new partial template --- templates/partial/filter.html | 42 +---------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 83ec7b2d..e7af7286 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -9,46 +9,8 @@

Filter

-
-
-
-
-

Selected filters

-
- -
- {% if label_clear_href|get_item:"domain"|length > 0 %} -

Domain

- - {% endif %} - {% if label_clear_href|get_item:"classifications"|length > 0 %} -

Security Classifications

- - {% endif %} -
+ {% include "partial/selected_filters.html" %}
From c3ccd25d746d0053d830e2dc6bbc9b8d076323e6 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:09:25 +0000 Subject: [PATCH 16/60] refactor domain and subdomain choices to get the urn value --- home/forms/search.py | 4 ++-- home/service/search.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index cfe95434..7abf16de 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -10,7 +10,7 @@ def get_domain_choices() -> list[tuple[str, str]]: # facets = client.search_facets() # domain_list = facets.options("domains") return [ - ("", "Select ..."), + ("", "All Domains"), ("urn:li:domain:HMCTS", "HMCTS"), ("urn:li:domain:HMPPS", "HMPPS"), ("urn:li:domain:HQ", "HQ"), @@ -80,7 +80,7 @@ def get_classification_choices(): def get_where_to_access_choices(): - return [("Analytical_Platform", "Analytical Platform")] + return [("analytical_platform", "Analytical Platform")] class SearchForm(forms.Form): diff --git a/home/service/search.py b/home/service/search.py index 234e6a2c..677556b6 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -14,7 +14,8 @@ def domains_with_their_subdomains(domain: str) -> list[str]: we filter by domain alone. We need to include all possible subdomains in the filter. """ subdomains = get_subdomain_choices(domain) - return [domain, *subdomains] if subdomains else subdomains + subdomains = [subdomain[0] for subdomain in subdomains] + return [domain, *subdomains] if subdomains else [domain] class SearchService(GenericService): From 001becb2dcd45bbf069f49b950861d955a8f6a82 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:10:37 +0000 Subject: [PATCH 17/60] build filter strings method to create filter search strings --- home/service/search.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/home/service/search.py b/home/service/search.py index 677556b6..6de47a17 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -27,6 +27,16 @@ def __init__(self, form: SearchForm, page: str, items_per_page: int = 20): self.paginator = self._get_paginator(items_per_page) self.context = self._get_context() + @staticmethod + def _build_filter_strings( + filter_param: str, filter_value_list: list[str] + ) -> list[str]: + return ( + [f"{filter_param}{filter_value}" for filter_value in filter_value_list] + if filter_value_list + else [] + ) + def _get_search_results(self, page: str, items_per_page: int): if self.form.is_bound: form_data = self.form.cleaned_data From 298b8c16d037ceee29d8dec47d3b2632cdf51fba Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:12:07 +0000 Subject: [PATCH 18/60] refactor classifications and where to access string generation, remove full query builder --- home/service/search.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index 6de47a17..b2666f54 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -47,21 +47,20 @@ def _get_search_results(self, page: str, items_per_page: int): sort = form_data.get("sort", "relevance") domain = form_data.get("domain", "") domains_and_subdomains = domains_with_their_subdomains(domain) - filter_value = ( - [MultiSelectFilter("domains", domains_and_subdomains)] - if domains_and_subdomains - else [] + classifications = self._build_filter_strings( + "sensitivityLevel=", form_data.get("classifications", []) ) + where_to_access = self._build_filter_strings( + "whereToAccessDataset=", form_data.get("where_to_access", []) + ) + filter_value = [] + if domains_and_subdomains: + filter_value.append(MultiSelectFilter("domains", domains_and_subdomains)) + if classifications: + filter_value.append(MultiSelectFilter("customProperties", classifications)) + if where_to_access: + filter_value.append(MultiSelectFilter("customProperties", where_to_access)) - classifications = form_data.get("classifications", []) - where_to_access = form_data.get("where_to_access", []) - - custom_properties = { - "classifications": classifications, - "where_to_access": where_to_access, - } - - full_query = self._query_builder(query, custom_properties) page_for_search = str(int(page) - 1) if sort == "ascending": sort_option = SortOption(field="name", ascending=True) @@ -71,7 +70,7 @@ def _get_search_results(self, page: str, items_per_page: int): sort_option = None results = self.client.search( - query=full_query, + query=query, page=page_for_search, filters=filter_value, sort=sort_option, From 64ff26fd3cf580c7a28aac4c4b551b3eb7b14e38 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:14:06 +0000 Subject: [PATCH 19/60] refactor where to access href creation --- home/service/search.py | 73 +++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index b2666f54..5ecf1d76 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -84,30 +84,49 @@ def _get_paginator(self, items_per_page: int) -> Paginator: return Paginator(pages_list, items_per_page) - def _get_context(self) -> dict[str, Any]: - if self.form["query"].value(): - page_title = f'Search for "{self.form["query"].value()}" - Data catalogue' - else: - page_title = "Search - Data catalogue" - + def _generate_label_clear_ref(self) -> dict[str, dict[str, str]]: if self.form.is_bound: domain = self.form.cleaned_data.get("domain", "") classifications = self.form.cleaned_data.get("classifications", []) + where_to_access = self.form.cleaned_data.get("where_to_access", []) label_clear_href = {} if domain: label_clear_href["domain"] = { - domain.split(":")[-1]: (self.form.encode_without_filter(domain)) + domain.split(":")[-1]: ( + self.form.encode_without_filter( + filter_name="domain", filter_value=domain + ) + ) } if classifications: classifications_clear_href = {} for classification in classifications: classifications_clear_href[ - classification.split("=")[1] - ] = self.form.encode_without_filter(classification) + classification + ] = self.form.encode_without_filter( + filter_name="classifications", filter_value=classification + ) label_clear_href["classifications"] = classifications_clear_href + + if where_to_access: + where_to_access_clear_href = {} + for access in where_to_access: + where_to_access_clear_href[ + access + ] = self.form.encode_without_filter( + filter_name="where_to_access", filter_value=access + ) + label_clear_href["availability"] = where_to_access_clear_href else: label_clear_href = None - print(f"label clear ref: {label_clear_href}") + return label_clear_href + + def _get_context(self) -> dict[str, Any]: + if self.form["query"].value(): + page_title = f'Search for "{self.form["query"].value()}" - Data catalogue' + else: + page_title = "Search - Data catalogue" + context = { "form": self.form, "results": self.results.page_results, @@ -118,39 +137,7 @@ def _get_context(self) -> dict[str, Any]: ), "paginator": self.paginator, "total_results": self.results.total_results, - "label_clear_href": label_clear_href, + "label_clear_href": self._generate_label_clear_ref(), } return context - - @staticmethod - def _query_builder(query: str, custom_properties: dict[str, list[str]]) -> str: - """Construct a valid DataHub search query using the input query and the passed - customProperties. - - Args: - query (str): User search string - custom_properties (dict[str, list[str | None]]): Dictionary of custom - property name and custom property values selected to filter on. - - Returns: - str: advanced query string to pass to DataHub that will include 'filtering' - logic for custom properties - """ - # ref: https://datahubproject.io/docs/how/search/#advanced-queries - custom_property_query: str = "/q customProperties: " - custom_property_strings: list[str] = [] - - for _, value in custom_properties.items(): - if value: - # within-filter options are inclusive OR - custom_property_string = " OR ".join(value) - custom_property_strings.append(custom_property_string) - - if query != "": - custom_property_strings.append(query) - - # cross-filter options are exclusive AND - final_query = " AND ".join(custom_property_strings) - - return f"{custom_property_query} {final_query}" if final_query else "*" From 78fa7101244b173f6b0c295c9f6430bd44905e17 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:16:08 +0000 Subject: [PATCH 20/60] add get_keys and format_label template filter functions --- home/templatetags/clear_filter.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/home/templatetags/clear_filter.py b/home/templatetags/clear_filter.py index b8538909..6bdef7de 100644 --- a/home/templatetags/clear_filter.py +++ b/home/templatetags/clear_filter.py @@ -4,12 +4,22 @@ @register.filter -def get_item(dictionary, key): - print(key) - print(dictionary) +def get_item(dictionary: dict[str, dict], key: str) -> dict[str, list | str]: return dictionary.get(key) @register.filter -def get_items(dictionary, key): +def get_items(dictionary: dict[str, dict], key: str) -> list: return dictionary.get(key).items() + + +@register.filter +def get_keys(dictionary: dict[str, dict]) -> list[str] | list: + if dictionary: + return dictionary.keys() + return [] + + +@register.filter +def format_label(label: str) -> str: + return label.replace("_", " ").title() if "_" in label else label From d76b377fc5af3648dfd7be2221b2ddbdea4e9d94 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:16:54 +0000 Subject: [PATCH 21/60] Update broken tests --- tests/selenium/conftest.py | 16 +++++++-- tests/selenium/test_search_scenarios.py | 48 ++++++++++++------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/tests/selenium/conftest.py b/tests/selenium/conftest.py index 35c5c636..2705904a 100644 --- a/tests/selenium/conftest.py +++ b/tests/selenium/conftest.py @@ -9,6 +9,7 @@ from selenium.webdriver.common.by import By from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.webdriver.remote.webelement import WebElement +from selenium.webdriver.support.select import Select TMP_DIR = Path(__file__).parent / "../../tmp" @@ -115,8 +116,19 @@ def checked_domain_checkboxes(self) -> list[WebElement]: def checked_sort_option(self) -> WebElement: return self.selenium.find_element(By.CSS_SELECTOR, "input:checked[name='sort']") - def domain_label(self, name) -> WebElement: - return self.selenium.find_element(By.XPATH, f"//label[ text() = '{name}' ]") + def domain_select(self) -> WebElement: + return Select(self.selenium.find_element(By.ID, "id_domain")) + + def select_domain(self, domain) -> WebElement: + select = self.domain_select() + return select.select_by_visible_text(domain) + + def get_selected_domain(self) -> WebElement: + select = self.domain_select() + return select.first_selected_option + + def domain_option(self, name) -> WebElement: + return self.selenium.find_element(By.XPATH, f"//option[ text() = '{name}' ]") def sort_label(self, name) -> WebElement: return self.selenium.find_element(By.XPATH, f"//label[ text() = '{name}' ]") diff --git a/tests/selenium/test_search_scenarios.py b/tests/selenium/test_search_scenarios.py index e8d80d63..a6d972c2 100644 --- a/tests/selenium/test_search_scenarios.py +++ b/tests/selenium/test_search_scenarios.py @@ -46,13 +46,13 @@ def test_apply_domain_filters(self): """ Interacts with the filters on the left hand side """ + domain = "HMPPS" self.start_on_the_search_page() - self.select_domain(["HMCTS", "HMPPS"]) + self.select_domain(domain) self.click_apply_filters() self.verify_i_am_on_the_search_page() self.verify_i_have_results() - self.verify_domain_selected(["HMCTS", "HMPPS"]) - self.verify_selected_filters_shown(["HMCTS", "HMPPS"]) + self.verify_domain_selected(domain) def test_pagination(self): """ @@ -85,8 +85,9 @@ def test_filters_query_and_sort_persist(self): Search settings persist as the user continues to interact with the search page. """ + domain = "HMPPS" self.start_on_the_search_page() - self.select_domain(["HMCTS", "HMPPS"]) + self.select_domain(domain) self.click_apply_filters() self.enter_a_query_and_submit("nomis") self.click_sort_option("Ascending") @@ -94,7 +95,7 @@ def test_filters_query_and_sort_persist(self): self.verify_i_have_results() self.verify_the_search_bar_has_value("nomis") - self.verify_domain_selected(["HMCTS", "HMPPS"]) + self.verify_domain_selected(domain) self.verify_sort_selected("Ascending") def test_adding_a_query_resets_pagination(self): @@ -117,7 +118,7 @@ def test_adding_a_filter_resets_pagination(self): self.click_next_page() self.verify_page("2") - self.select_domain(["HMPPS"]) + self.select_domain("HMPPS") self.click_apply_filters() self.verify_page("1") @@ -126,23 +127,25 @@ def test_clear_single_filter(self): Users can clear a filter by clicking on it within the "selected filters" panel. """ + domain = "HMPPS" self.start_on_the_search_page() - self.select_domain(["HMPPS", "HMCTS"]) + self.select_domain(domain) self.click_apply_filters() - self.click_clear_selected_filter("HMPPS") - - self.verify_domain_selected(["HMCTS"]) + self.verify_domain_selected(domain) + self.click_clear_selected_filter(domain) + self.verify_unselected_domain() def test_clear_all_filters(self): """ Users can click a button to clear all filters. """ + domain = "HMCTS" self.start_on_the_search_page() - self.select_domain(["HMPPS", "HMCTS"]) + self.select_domain(domain) self.click_apply_filters() + self.verify_domain_selected(domain) self.click_clear_filters() - - self.verify_domain_selected([]) + self.verify_unselected_domain() def test_automated_accessibility_home(self): self.start_on_the_home_page() @@ -195,9 +198,8 @@ def enter_a_query_and_submit(self, query): search_bar.send_keys(query) self.click_on_the_search_button() - def select_domain(self, domains): - for domain in domains: - self.search_page.domain_label(domain).click() + def select_domain(self, domain): + self.search_page.select_domain(domain) def click_sort_option(self, sortby): self.search_page.sort_label(sortby).click() @@ -216,15 +218,13 @@ def verify_the_search_bar_has_value(self, query): assert search_bar.get_attribute("value") == query - def verify_domain_selected(self, domains): - expected = set(domains) - checkboxes = self.search_page.checked_domain_checkboxes() - actual = set() - for checkbox in checkboxes: - value = checkbox.get_attribute("value") or "" - actual.add(value.replace("urn:li:domain:", "")) + def verify_domain_selected(self, domain): + selected_domain = self.search_page.get_selected_domain().text + assert selected_domain == domain - assert actual == expected + def verify_unselected_domain(self): + selected_domain = self.search_page.get_selected_domain().text + assert selected_domain == "All Domains" def verify_selected_filters_shown(self, domains): actual = {i.text for i in self.search_page.selected_filter_tags()} From 9858ab8bf45b73b744eaaef749fab3b90f85d185 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:17:32 +0000 Subject: [PATCH 22/60] add selected filters partial --- templates/partial/selected_filters.html | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 templates/partial/selected_filters.html diff --git a/templates/partial/selected_filters.html b/templates/partial/selected_filters.html new file mode 100644 index 00000000..59fb38f1 --- /dev/null +++ b/templates/partial/selected_filters.html @@ -0,0 +1,35 @@ +{% load future %} +{% load clear_filter %} +
+
+
+

Selected filters

+
+
+

+ {% if label_clear_href|get_keys|length > 0 %} + + Clear filter + + {% endif %} +

+
+
+ {% if label_clear_href|get_keys|length > 0 %} + {% for key in label_clear_href|get_keys %} + {% if label_clear_href|get_item:key|length > 0 %} +

{{key|title}}

+ + {% endif %} + {% endfor %} + {% endif %} +
From cafc0122402738f9636a2cc241eaa0f9bf9cf901 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:18:28 +0000 Subject: [PATCH 23/60] update packages --- package-lock.json | 667 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 668 insertions(+) diff --git a/package-lock.json b/package-lock.json index 8be152aa..7ca1eb62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,10 +6,49 @@ "": { "dependencies": { "@ministryofjustice/frontend": "^2.1.0", + "axe": "^12.2.3", "govuk-frontend": "^5.0.0", "sass": "^1.70.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ladjs/format-util": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@ladjs/format-util/-/format-util-1.0.4.tgz", + "integrity": "sha512-hZere0rUga8kTzSTFbHREXpD9E/jwi94+B5RyLAmMIzl/w/EK1z7rFEnMHzPkU4AZkL42JWSsGXoV8LXMihybg==" + }, "node_modules/@ministryofjustice/frontend": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-2.1.0.tgz", @@ -25,6 +64,38 @@ "jquery": "^3.6.0" } }, + "node_modules/@strikeentco/get": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@strikeentco/get/-/get-1.0.1.tgz", + "integrity": "sha512-qPnoWkt7xxcOaUJhMveDHmj6INVKHXUEsPTGz3g4HC5XNnqRd1dDEFxL1KpG+vZ2VxmRK42EjBt5vUDr4uLzQQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@strikeentco/set": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@strikeentco/set/-/set-1.0.2.tgz", + "integrity": "sha512-jP/wGhBi70RoD2Ww2bd3Ay4nzKfyWSPL/sDgFaq2e/FXNC9a04R0M7fuDVHG/dG+WWNVj2pmE9exXn20a0AjGg==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -37,6 +108,30 @@ "node": ">= 8" } }, + "node_modules/axe": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/axe/-/axe-12.2.3.tgz", + "integrity": "sha512-ZZ1kJi7ygeMPoVUgIkFcFbN+Wr/gYusdDWkBZNxu6ZMxAaTE3vnfLHeDR+1TQSZBE0l3qpqKKHHef2FRz8N83g==", + "dependencies": { + "@ladjs/format-util": "^1.0.4", + "@strikeentco/get": "1.0.1", + "@strikeentco/set": "1.0.2", + "boolean": "3.2.0", + "console-polyfill": "0.3.0", + "format-specifiers": "^1.0.0", + "is-symbol": "^1.0.4", + "iserror": "0.0.2", + "merge-options": "3.0.4", + "p-map-series": "2", + "parse-app-info": "^5.0.0", + "parse-err": "^1.0.0", + "pick-deep": "1.0.0", + "unset-value": "2.0.1" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -45,6 +140,11 @@ "node": ">=8" } }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -56,6 +156,19 @@ "node": ">=8" } }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -82,6 +195,48 @@ "fsevents": "~2.3.2" } }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/console-polyfill": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/console-polyfill/-/console-polyfill-0.3.0.tgz", + "integrity": "sha512-w+JSDZS7XML43Xnwo2x5O5vxB0ID7T5BdqDtyqT6uiCAX2kZAgcWxNaGqT97tZfSHzfOcvrfsDAodKcJ3UvnXQ==" + }, + "node_modules/dotgitconfig": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/dotgitconfig/-/dotgitconfig-1.1.2.tgz", + "integrity": "sha512-M+nUsYHJT2qs6bnYqotmO+1IQ09w3ZwLcX4MmbblaWN9C7ydDWM2xQLv22xfl4bUxienESi1GsZnZJPb8jslqQ==", + "dependencies": { + "ini": "^1.3.5" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -93,6 +248,23 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/format-specifiers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/format-specifiers/-/format-specifiers-1.0.0.tgz", + "integrity": "sha512-/xcmy6xn/DsR+V6flFj3E47yCbrsk70r90moAMENVkKckUPUG9CRE79S/2xajLVx1iADIoWx+1R304uMXB/riQ==" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -106,6 +278,33 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-3.0.1.tgz", + "integrity": "sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/get-value/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -125,11 +324,84 @@ "node": ">= 4.2.0" } }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-2.0.2.tgz", + "integrity": "sha512-ybKOlcRsK2MqrM3Hmz/lQxXHZ6ejzSPzpNabKB45jb5qDgJvKPa3SdapTsTLwEb9WltgWpOmNax7i+DzNOk4TA==", + "dependencies": { + "get-value": "^3.0.0", + "has-values": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-values": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-2.0.1.tgz", + "integrity": "sha512-+QdH3jOmq9P8GfdjFg0eJudqx1FqU62NQJ4P16rOEHeRdl7ckgwn6uqQjzYE0ZoHVV/e5E2esuJ5Gl5+HUW19w==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/ip": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -141,6 +413,17 @@ "node": ">=8" } }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -168,12 +451,116 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/iserror": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/iserror/-/iserror-0.0.2.tgz", + "integrity": "sha512-oKGGrFVaWwETimP3SiWwjDeY27ovZoyZPHtxblC4hCq9fXxed/jasx+ATWFFjCVSRZng8VTMsN1nDnGo6zMBSw==" + }, + "node_modules/isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jquery": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", "peer": true }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/last-commit-log": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/last-commit-log/-/last-commit-log-3.3.0.tgz", + "integrity": "sha512-qYzhTltQvQ/mMIDWnG16KyUi79y4F5uEqHDDbAJm2HLuWgDuBhZ8g5PyWomYV0wsDQDuYcPWMQdJ91wsZOZ5NQ==", + "dependencies": { + "dotgitconfig": "^1.1.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -182,6 +569,25 @@ "node": "*" } }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -190,6 +596,115 @@ "node": ">=0.10.0" } }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map-series": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz", + "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-app-info": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-app-info/-/parse-app-info-5.0.0.tgz", + "integrity": "sha512-uP4Bcso/FvnPpPmO5iPszdf0HoqugxoYjXxnosL6XBxR8gRl78NJdKoRxrsTESeYQv4qN4jThPsCxdmEzpIZ5g==", + "dependencies": { + "ip": "^1.1.8", + "last-commit-log": "^3.3.0", + "lodash": "^4.17.21", + "read-pkg-up": "7", + "semver": "^7.5.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/parse-err": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-err/-/parse-err-1.0.0.tgz", + "integrity": "sha512-K2RCrbPe7CXezMfRQTZJgCOQB6kyUofAkEriwGfaP4oiwbRm3YDTG6F8qEBSFVA7QiLzph/rMqokPcOz26UxSw==", + "dependencies": { + "iserror": "^0.0.2" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/pick-deep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pick-deep/-/pick-deep-1.0.0.tgz", + "integrity": "sha512-Uy0VUtabou1sPl/vVClBFrWi4Ae/D3Vqu44FJawmm4lnduu5E16ykw8kh15fiUeLQ6lbmXQ0EMr3YIsqpLZl+A==", + "dependencies": { + "@strikeentco/get": "^1.0.0", + "@strikeentco/set": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -201,6 +716,44 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "engines": { + "node": ">=8" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -212,6 +765,22 @@ "node": ">=8.10.0" } }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sass": { "version": "1.70.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", @@ -228,6 +797,20 @@ "node": ">=14.0.0" } }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -236,6 +819,56 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -246,6 +879,40 @@ "engines": { "node": ">=8.0" } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/unset-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-2.0.1.tgz", + "integrity": "sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg==", + "dependencies": { + "has-value": "^2.0.2", + "isobject": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index ece087f8..581dff3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "dependencies": { "@ministryofjustice/frontend": "^2.1.0", + "axe": "^12.2.3", "govuk-frontend": "^5.0.0", "sass": "^1.70.0" }, From 39fc25a80f762165026bf6d35e635b836636545e Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 22:11:49 +0000 Subject: [PATCH 24/60] refactor encode_without_filter function --- home/forms/search.py | 89 ++++++++++++++++++++++-------------------- home/service/search.py | 2 +- 2 files changed, 48 insertions(+), 43 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index 7abf16de..0fec3f95 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -129,49 +129,54 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.initial["sort"] = "relevance" - def _clean_custom_property( - self, custom_property: str, property_name: str - ) -> list[str]: - """Helper function to style DataHub customProperties into their search syntax - (customPropertyName="custom property"). Reformats the 'cleaned_data' list for a - property. - - ref: https://datahubproject.io/docs/how/search/#advanced-queries - - Args: - custom_property (str): Name of the custom property object in this codebase - property_name (str): Name of the custom property in DataHub - - Returns: - list[str]: List of reformatted custom properties. - """ - cleaned_properties = [] - properties = self.cleaned_data.get(custom_property, []) - for option in properties: - cleaned_properties.append(f"{property_name}={option}") - return cleaned_properties - - def clean_classifications(self): - cleaned_classifications = self._clean_custom_property( - custom_property="classifications", property_name="sensitivityLevel" - ) - return cleaned_classifications - - def clean_where_to_access(self): - cleaned_where_to_access = self._clean_custom_property( - custom_property="where_to_access", - property_name="whereToAccessDataset", - ) - return cleaned_where_to_access - - def encode_without_filter(self, filter_to_remove): + # def _clean_custom_property( + # self, custom_property: str, property_name: str + # ) -> list[str]: + # """Helper function to style DataHub customProperties into their search syntax + # (customPropertyName="custom property"). Reformats the 'cleaned_data' list for a + # property. + + # ref: https://datahubproject.io/docs/how/search/#advanced-queries + + # Args: + # custom_property (str): Name of the custom property object in this codebase + # property_name (str): Name of the custom property in DataHub + + # Returns: + # list[str]: List of reformatted custom properties. + # """ + # cleaned_properties = [] + # properties = self.cleaned_data.get(custom_property, []) + # for option in properties: + # cleaned_properties.append(f"{property_name}={option}") + # return cleaned_properties + + # def clean_classifications(self): + # cleaned_classifications = self._clean_custom_property( + # custom_property="classifications", property_name="sensitivityLevel" + # ) + # return cleaned_classifications + + # def clean_where_to_access(self): + # cleaned_where_to_access = self._clean_custom_property( + # custom_property="where_to_access", + # property_name="whereToAccessDataset", + # ) + # return cleaned_where_to_access + + def encode_without_filter(self, filter_name: str, filter_value: str): """Preformat hrefs to drop individual filters""" # Deepcopy the cleaned data dict to avoid modifying it inplace query_params = deepcopy(self.cleaned_data) - domain = query_params.get("domain") - classifications = query_params.get("classifications") - if domain == filter_to_remove: - query_params.pop("domain") - elif filter_to_remove in classifications: - query_params["classifications"].remove(filter_to_remove) + value = query_params.get(filter_name) + if isinstance(value, list) and filter_value in value: + value.remove(filter_value) + elif isinstance(value, str) and filter_value == value: + query_params.pop(filter_name) + # domain = query_params.get("domain") + # classifications = query_params.get("classifications") + # if domain == filter_to_remove: + # query_params.pop("domain") + # elif filter_to_remove in classifications: + # query_params["classifications"].remove(filter_to_remove) return f"?{urlencode(query_params, doseq=True)}" diff --git a/home/service/search.py b/home/service/search.py index 5ecf1d76..97fef3af 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -15,7 +15,7 @@ def domains_with_their_subdomains(domain: str) -> list[str]: """ subdomains = get_subdomain_choices(domain) subdomains = [subdomain[0] for subdomain in subdomains] - return [domain, *subdomains] if subdomains else [domain] + return [domain, *subdomains] if subdomains else [] class SearchService(GenericService): From 93679f47e20330600f7874f1aed4ec47b2a0de45 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 09:18:29 +0000 Subject: [PATCH 25/60] remove redundant code --- home/forms/search.py | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index 0fec3f95..ffdd57a3 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -129,41 +129,6 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.initial["sort"] = "relevance" - # def _clean_custom_property( - # self, custom_property: str, property_name: str - # ) -> list[str]: - # """Helper function to style DataHub customProperties into their search syntax - # (customPropertyName="custom property"). Reformats the 'cleaned_data' list for a - # property. - - # ref: https://datahubproject.io/docs/how/search/#advanced-queries - - # Args: - # custom_property (str): Name of the custom property object in this codebase - # property_name (str): Name of the custom property in DataHub - - # Returns: - # list[str]: List of reformatted custom properties. - # """ - # cleaned_properties = [] - # properties = self.cleaned_data.get(custom_property, []) - # for option in properties: - # cleaned_properties.append(f"{property_name}={option}") - # return cleaned_properties - - # def clean_classifications(self): - # cleaned_classifications = self._clean_custom_property( - # custom_property="classifications", property_name="sensitivityLevel" - # ) - # return cleaned_classifications - - # def clean_where_to_access(self): - # cleaned_where_to_access = self._clean_custom_property( - # custom_property="where_to_access", - # property_name="whereToAccessDataset", - # ) - # return cleaned_where_to_access - def encode_without_filter(self, filter_name: str, filter_value: str): """Preformat hrefs to drop individual filters""" # Deepcopy the cleaned data dict to avoid modifying it inplace @@ -173,10 +138,4 @@ def encode_without_filter(self, filter_name: str, filter_value: str): value.remove(filter_value) elif isinstance(value, str) and filter_value == value: query_params.pop(filter_name) - # domain = query_params.get("domain") - # classifications = query_params.get("classifications") - # if domain == filter_to_remove: - # query_params.pop("domain") - # elif filter_to_remove in classifications: - # query_params["classifications"].remove(filter_to_remove) return f"?{urlencode(query_params, doseq=True)}" From a98d658d62317c44ed864af23904cfebfc233d92 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 11:20:51 +0000 Subject: [PATCH 26/60] update tests with singular domain, classifications and where_to_access --- tests/conftest.py | 6 ++++-- tests/test_forms.py | 22 ++++++++++++++++------ tests/test_services.py | 32 ++++++++++++++++++++++++++++---- tests/test_views.py | 2 +- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 4241f355..c9450b77 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -83,7 +83,7 @@ def mock_search_response(mock_catalogue, total_results=0, page_results=()): def mock_search_facets_response(mock_catalogue, domains): - mock_catalogue.search_facets.return_value = SearchFacets({"domains": domains}) + mock_catalogue.search_facets.return_value = SearchFacets({"domain": domains}) @pytest.fixture @@ -91,7 +91,9 @@ def valid_form(): valid_form = SearchForm( data={ "query": "test", - "domains": ["urn:li:domain:HMCTS"], + "domain": "urn:li:domain:HMCTS", + "classifications": ["OFFICIAL"], + "where_to_access": ["analytical_platform"], "sort": "ascending", "clear_filter": False, "clear_label": False, diff --git a/tests/test_forms.py b/tests/test_forms.py index 3fd173bc..b972a7b1 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -7,7 +7,7 @@ def test_query_field_length(self): assert not SearchForm(data={"query": over_100_characters}).is_valid() def test_domain_is_from_domain_list_false(self): - assert not SearchForm(data={"domains": ["fake"]}).is_valid() + assert not SearchForm(data={"domain": ["fake"]}).is_valid() def test_sort_is_from_sort_list_false(self): assert not SearchForm(data={"sort": ["fake"]}).is_valid() @@ -16,22 +16,32 @@ def test_all_fields_nullable(self): assert SearchForm(data={}).is_valid() def test_form_encode_without_filter_for_one_filter(self, valid_form): - assert valid_form.encode_without_filter("urn:li:domain:HMCTS") == ( - "?query=test&" "sort=ascending&" "clear_filter=False&" "clear_label=False" + assert valid_form.encode_without_filter( + filter_name="domain", filter_value="urn:li:domain:HMCTS" + ) == ( + "?query=test&" + "classifications=OFFICIAL&" + "where_to_access=analytical_platform&" + "sort=ascending&" + "clear_filter=False&" + "clear_label=False" ) def test_form_encode_without_filter_for_two_filters(self): two_filter_form = SearchForm( data={ "query": "test", - "domains": ["urn:li:domain:HMCTS", "urn:li:domain:HMPPS"], + "domain": "urn:li:domain:HMCTS", + "classifications": ["OFFICIAL"], } ) two_filter_form.is_valid() - assert two_filter_form.encode_without_filter("urn:li:domain:HMCTS") == ( + assert two_filter_form.encode_without_filter( + filter_name="domain", filter_value="urn:li:domain:HMCTS" + ) == ( "?query=test&" - "domains=urn%3Ali%3Adomain%3AHMPPS&" + "classifications=OFFICIAL&" "sort=&" "clear_filter=False&" "clear_label=False" diff --git a/tests/test_services.py b/tests/test_services.py index 5929d43b..13f974b3 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -23,9 +23,33 @@ def test_get_context_page_title(self, search_context): assert search_context["page_title"] == 'Search for "test" - Data catalogue' def test_get_context_label_clear_href(self, search_context): - assert search_context["label_clear_href"] == { + assert search_context["label_clear_href"]["domain"] == { "HMCTS": ( "?query=test&" + "classifications=OFFICIAL&" + "where_to_access=analytical_platform&" + "sort=ascending&" + "clear_filter=False&" + "clear_label=False" + ) + } + + assert search_context["label_clear_href"]["availability"] == { + "analytical_platform": ( + "?query=test&" + "domain=urn%3Ali%3Adomain%3AHMCTS&" + "classifications=OFFICIAL&" + "sort=ascending&" + "clear_filter=False&" + "clear_label=False" + ) + } + + assert search_context["label_clear_href"]["classifications"] == { + "OFFICIAL": ( + "?query=test&" + "domain=urn%3Ali%3Adomain%3AHMCTS&" + "where_to_access=analytical_platform&" "sort=ascending&" "clear_filter=False&" "clear_label=False" @@ -52,16 +76,16 @@ def test_get_context(self, detail_context, mock_catalogue): @pytest.mark.parametrize( "domain, expected_subdomains", [ - ("does-not-exist", ["does-not-exist"]), + ("does-not-exist", []), ( "urn:li:domain:HMPPS", [ + "urn:li:domain:HMPPS", "urn:li:domain:2feb789b-44d3-4412-b998-1f26819fabf9", "urn:li:domain:abe153c1-416b-4abb-be7f-6accf2abb10a", - "urn:li:domain:HMPPS", ], ), ], ) def test_domain_expansion(domain, expected_subdomains): - assert domains_with_their_subdomains([domain]) == expected_subdomains + assert domains_with_their_subdomains(domain) == expected_subdomains diff --git a/tests/test_views.py b/tests/test_views.py index cf13a1d5..0117fd3a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -27,7 +27,7 @@ def test_exposes_query(self, client): assert response.context["form"].cleaned_data["query"] == "foo" def test_bad_form(self, client): - response = client.get(reverse("home:search"), data={"domains": "fake"}) + response = client.get(reverse("home:search"), data={"domain": "fake"}) assert response.status_code == 400 From e827a3e895c86ba3a699585a1e3533faf3790a97 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 11:23:07 +0000 Subject: [PATCH 27/60] Update dingular domain and add linting fixes --- home/forms/search.py | 10 ++++++++-- home/helper.py | 2 +- home/service/search.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index ffdd57a3..6d1dad96 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -8,7 +8,7 @@ def get_domain_choices() -> list[tuple[str, str]]: """Make API call to obtain domain choices""" # TODO: pull in the domains from the catalogue client # facets = client.search_facets() - # domain_list = facets.options("domains") + # domain_list = facets.options("domain") return [ ("", "All Domains"), ("urn:li:domain:HMCTS", "HMCTS"), @@ -95,7 +95,13 @@ class SearchForm(forms.Form): domain = forms.ChoiceField( choices=get_domain_choices, required=False, - widget=forms.Select(attrs={"form": "searchform", "class": "govuk-select"}), + widget=forms.Select( + attrs={ + "form": "searchform", + "class": "govuk-select", + "aria-label": "domain", + } + ), ) classifications = forms.MultipleChoiceField( choices=get_classification_choices, diff --git a/home/helper.py b/home/helper.py index fecc2622..b5eb644e 100644 --- a/home/helper.py +++ b/home/helper.py @@ -8,5 +8,5 @@ def filter_seleted_domains(domain_list, domains): def get_domain_list(client): facets = client.search_facets() - domain_list = facets.options("domains") + domain_list = facets.options("domain") return domain_list diff --git a/home/service/search.py b/home/service/search.py index 97fef3af..00687dba 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -55,7 +55,7 @@ def _get_search_results(self, page: str, items_per_page: int): ) filter_value = [] if domains_and_subdomains: - filter_value.append(MultiSelectFilter("domains", domains_and_subdomains)) + filter_value.append(MultiSelectFilter("domain", domains_and_subdomains)) if classifications: filter_value.append(MultiSelectFilter("customProperties", classifications)) if where_to_access: From c78026b2c2f8df389d68eb4e701df5443cffc2f8 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 12:01:07 +0000 Subject: [PATCH 28/60] linter updates --- home/service/search.py | 10 +++++----- tests/conftest.py | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index f16ee6ed..e6431fd7 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -1,8 +1,9 @@ -from typing import Any +import re from copy import deepcopy +from typing import Any + from data_platform_catalogue.search_types import MultiSelectFilter, SortOption from django.core.paginator import Paginator -import re from home.forms.search import SearchForm, get_subdomain_choices @@ -155,12 +156,11 @@ def _highlight_results(self): return highlighted_results else: - pattern = f'({re.escape(query)})' + pattern = f"({re.escape(query)})" for result in highlighted_results.page_results: result.description = re.sub( - pattern, r'**\1**', result.description, flags=re.IGNORECASE, + pattern, r"**\1**", result.description, flags=re.IGNORECASE ) - return highlighted_results def _get_match_reason_display_names(self): diff --git a/tests/conftest.py b/tests/conftest.py index 4d00abc3..03696c8e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -32,7 +32,7 @@ def generate_page(page_size=20): result_type=choice((ResultType.DATA_PRODUCT, ResultType.TABLE)), name=fake.name(), description=fake.paragraph(), - metadata={"search_summary":"a"}, + metadata={"search_summary": "a"}, ) ) return results @@ -109,6 +109,7 @@ def valid_form(): def search_service(valid_form): return SearchService(form=valid_form, page="1") + @pytest.fixture def search_context(search_service): return search_service.context From f4a87859822e605d8fe4dee02f90a9a5a32efa31 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Wed, 21 Feb 2024 11:21:44 +0000 Subject: [PATCH 29/60] add service for dataproductdetails --- home/service/details.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/home/service/details.py b/home/service/details.py index 903eb8ce..b7f79009 100644 --- a/home/service/details.py +++ b/home/service/details.py @@ -1,10 +1,11 @@ from data_platform_catalogue.search_types import MultiSelectFilter, ResultType from django.core.exceptions import ObjectDoesNotExist + from .base import GenericService -class DetailsService(GenericService): +class DetailsDataProductService(GenericService): def __init__(self, urn: str): self.urn = urn self.client = self._get_catalogue_client() @@ -16,8 +17,38 @@ def __init__(self, urn: str): raise ObjectDoesNotExist(urn) self.result = search_results.page_results[0] + self.data_product_name = self.result.name + self.assets_in_data_product = self._get_data_product_entities() self.context = self._get_context() + def _get_data_product_entities(self): + # we might want to implement pagination for data product children + # details at some point + data_product_search = self.client.list_data_product_assets( + urn=self.urn, count=500 + ).page_results + + assets_in_data_product = [] + for result in data_product_search: + # name is like that as fully qualified name ({data_product}.{asset}) seems + # too verbose to display here. + assets_in_data_product.append( + { + "name": ( + result.name + if not result.name.split(".")[0] == self.data_product_name + else result.name.split(".")[1] + ), + "urn": result.id, + "description": result.description, + "type": "TABLE", + } + ) + + assets_in_data_product = sorted(assets_in_data_product, key=lambda d: d["name"]) + + return assets_in_data_product + def _get_context(self): context = { "result": self.result, @@ -26,6 +57,7 @@ def _get_context(self): if self.result.result_type == ResultType.DATA_PRODUCT else "Table" ), + "tables": self.assets_in_data_product, "page_title": f"{self.result.name} - Data catalogue", } From 35eb1cf747e09591ebe47b21de4330a98b255d55 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Wed, 21 Feb 2024 11:22:49 +0000 Subject: [PATCH 30/60] update templates - data product details and search --- ...details.html => details_data_product.html} | 30 ++++++++----------- templates/partial/search_result.html | 4 ++- 2 files changed, 15 insertions(+), 19 deletions(-) rename templates/{details.html => details_data_product.html} (80%) diff --git a/templates/details.html b/templates/details_data_product.html similarity index 80% rename from templates/details.html rename to templates/details_data_product.html index 001e81d8..b30ad60b 100644 --- a/templates/details.html +++ b/templates/details_data_product.html @@ -33,7 +33,7 @@

{{result.name}}

Domain name
- {{result.metadata.domain.properties.name}} + {{result.metadata.domain_name}}
@@ -57,7 +57,7 @@

{{result.name}}

Retention period
- + {{result.metadata.retention_period_in_days|intcomma}}
@@ -82,7 +82,7 @@

{{result.name}}


- + @@ -91,21 +91,15 @@

{{result.name}}

- - - - - - - - - - - - - - - + {% for table in tables %} + {% with table_type=table.type|lower %} + + + + + + {% endwith %} + {% endfor %}
Database contentData Product content
Table name
Table 1This is description about the table Schema details
Table 2This is description about the table Schema details
Table 3This is description about the table Schema details
{{table.name}}{{table.description}} Schema details
diff --git a/templates/partial/search_result.html b/templates/partial/search_result.html index 46996814..687ae625 100644 --- a/templates/partial/search_result.html +++ b/templates/partial/search_result.html @@ -6,7 +6,9 @@

- {{result.name}} + {% with result_type=result.result_type.name|lower %} + {{result.name}} + {% endwith %} {% if result.result_type.name == "DATA_PRODUCT" %} Data product From c920a04f5aaa7e1bc0810f9294ae400614e60157 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Wed, 21 Feb 2024 11:23:50 +0000 Subject: [PATCH 31/60] url for search link and details redirect in views --- home/service/search.py | 22 +++++++++++++--------- home/urls.py | 6 +++++- home/views.py | 16 ++++++++++++---- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index e6431fd7..dc3b223b 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -104,20 +104,20 @@ def _generate_label_clear_ref(self) -> dict[str, dict[str, str]]: if classifications: classifications_clear_href = {} for classification in classifications: - classifications_clear_href[ - classification - ] = self.form.encode_without_filter( - filter_name="classifications", filter_value=classification + classifications_clear_href[classification] = ( + self.form.encode_without_filter( + filter_name="classifications", filter_value=classification + ) ) label_clear_href["classifications"] = classifications_clear_href if where_to_access: where_to_access_clear_href = {} for access in where_to_access: - where_to_access_clear_href[ - access - ] = self.form.encode_without_filter( - filter_name="where_to_access", filter_value=access + where_to_access_clear_href[access] = ( + self.form.encode_without_filter( + filter_name="where_to_access", filter_value=access + ) ) label_clear_href["availability"] = where_to_access_clear_href else: @@ -156,10 +156,14 @@ def _highlight_results(self): return highlighted_results else: + pattern = f"({re.escape(query)})" pattern = f"({re.escape(query)})" for result in highlighted_results.page_results: result.description = re.sub( - pattern, r"**\1**", result.description, flags=re.IGNORECASE + pattern, + r"**\1**", + result.description, + flags=re.IGNORECASE, ) return highlighted_results diff --git a/home/urls.py b/home/urls.py index c9ec0a16..722cc492 100644 --- a/home/urls.py +++ b/home/urls.py @@ -7,6 +7,10 @@ urlpatterns = [ path("", views.home_view, name="home"), path("search", views.search_view, name="search"), - path("details//", views.details_view, name="details"), + path( + "details//", + views.redirect_details_view, + name="details", + ), path("pagination/", views.search_view, name="pagination"), ] diff --git a/home/views.py b/home/views.py index b7160dfd..565ae2cb 100644 --- a/home/views.py +++ b/home/views.py @@ -3,7 +3,7 @@ from django.shortcuts import render from home.forms.search import SearchForm -from home.service.details import DetailsService +from home.service.details import DetailsDataProductService from home.service.search import SearchService @@ -12,15 +12,23 @@ def home_view(request): return render(request, "home.html", context) -def details_view(request, id): +def redirect_details_view(request, result_type, id): + if result_type == "data_product": + context = data_product_details(request, id) + return render(request, "details_data_product.html", context) + if result_type == "table": + pass + + +def data_product_details(request, id): try: - service = DetailsService(id) + service = DetailsDataProductService(id) except ObjectDoesNotExist: raise Http404("Asset does not exist") context = service.context - return render(request, "details.html", context) + return context def search_view(request, page: str = "1"): From b6fda814e1bdbde030c4afd25966fe91caf48cef Mon Sep 17 00:00:00 2001 From: LavMatt Date: Wed, 21 Feb 2024 11:27:10 +0000 Subject: [PATCH 32/60] add tests for data product details and view --- tests/conftest.py | 33 +++++++++++++++++++++++++++------ tests/test_services.py | 35 +++++++++++++++++++++++++++-------- tests/test_views.py | 10 +++++++--- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 03696c8e..11fbf4e1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ import pytest from data_platform_catalogue.client import BaseCatalogueClient +from data_platform_catalogue.client.datahub.datahub_client import DataHubCatalogueClient from data_platform_catalogue.search_types import ( FacetOption, ResultType, @@ -14,13 +15,18 @@ from faker import Faker from home.forms.search import SearchForm -from home.service.details import DetailsService +from home.service.details import DetailsDataProductService from home.service.search import SearchService +from datahub.metadata.schema_classes import ( + DataProductPropertiesClass, + DataProductAssociationClass, +) + fake = Faker() -def generate_page(page_size=20): +def generate_page(page_size=20, result_type: ResultType = None): """ Generate a fake search page """ @@ -30,6 +36,11 @@ def generate_page(page_size=20): SearchResult( id=fake.unique.name(), result_type=choice((ResultType.DATA_PRODUCT, ResultType.TABLE)), + result_type=( + choice((ResultType.DATA_PRODUCT, ResultType.TABLE)) + if result_type is None + else result_type + ), name=fake.name(), description=fake.paragraph(), metadata={"search_summary": "a"}, @@ -70,7 +81,12 @@ def mock_catalogue(): mock_catalogue, page_results=generate_page(), total_results=100 ) mock_search_facets_response(mock_catalogue, domains=generate_options()) - + mock_list_data_product_response( + mock_catalogue, + page_results=generate_page(page_size=1, result_type=ResultType.TABLE), + total_results=1, + ) + # mock_get_dataproduct_aspect(mock_catalogue) yield mock_catalogue patcher.stop() @@ -84,7 +100,7 @@ def mock_search_response(mock_catalogue, total_results=0, page_results=()): def mock_search_facets_response(mock_catalogue, domains): - mock_catalogue.search_facets.return_value = SearchFacets({"domain": domains}) + mock_catalogue.search_facets.return_value = SearchFacets({"domains": domains}) @pytest.fixture @@ -116,10 +132,15 @@ def search_context(search_service): @pytest.fixture -def detail_context(mock_catalogue): +def detail_dataproduct_context(mock_catalogue): mock_catalogue.search.return_value = SearchResponse( total_results=1, page_results=generate_page(page_size=1) ) - details_service = DetailsService(urn="urn:li:dataProduct:test") + # mock_catalogue.list_data_product_assets.return_value = SearchResponse( + # total_results=1, + # page_results=generate_page(page_size=1, result_type=ResultType.TABLE), + # ) + # with patch(): + details_service = DetailsDataProductService(urn="urn:li:dataProduct:test") context = details_service._get_context() return context diff --git a/tests/test_services.py b/tests/test_services.py index 6cdcd3df..7122bda2 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -78,34 +78,53 @@ def test_highlight_results_with_case_insensitive_query(self): service = SearchService(form=form, page="1") descriptions = [result.description for result in service.results.page_results] - highlighted_descriptions = [result.description for result in service.highlighted_results.page_results] + highlighted_descriptions = [ + result.description for result in service.highlighted_results.page_results + ] assert descriptions != highlighted_descriptions assert ( "**a**" or "**A**" in highlighted.description - for normal, highlighted - in zip( + for normal, highlighted in zip( service.results.page_results, service.highlighted_results.page_results, ) if "a" or "A" in normal.description ) -class TestDetailsService: - def test_get_context(self, detail_context, mock_catalogue): - assert detail_context["result"] == mock_catalogue.search().page_results[0] + +class TestDetailsDataProductService: + def test_get_context_data_product(self, detail_dataproduct_context, mock_catalogue): + assert ( + detail_dataproduct_context["result"] + == mock_catalogue.search().page_results[0] + ) result_type = ( "Data product" if mock_catalogue.search().page_results[0].result_type == ResultType.DATA_PRODUCT else "Table" ) - assert detail_context["result_type"] == result_type + assert detail_dataproduct_context["result_type"] == result_type assert ( - detail_context["page_title"] + detail_dataproduct_context["page_title"] == f"{mock_catalogue.search().page_results[0].name} - Data catalogue" ) + def test_get_context_data_product_tables( + self, detail_dataproduct_context, mock_catalogue + ): + name = mock_catalogue.list_data_product_assets().page_results[0].name + mock_table = { + "name": name, + "urn": mock_catalogue.list_data_product_assets().page_results[0].id, + "description": mock_catalogue.list_data_product_assets() + .page_results[0] + .description, + "type": "TABLE", + } + assert detail_dataproduct_context["tables"][0] == mock_table + @pytest.mark.parametrize( "domain, expected_subdomains", diff --git a/tests/test_views.py b/tests/test_views.py index 0117fd3a..8bcbffac 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -32,15 +32,19 @@ def test_bad_form(self, client): class TestDetailsView: - def test_details(self, client): + def test_details_data_product(self, client): response = client.get( reverse("home:details", kwargs={"id": "urn:li:dataProduct:common-platform"}) ) assert response.status_code == 200 - def test_details_not_found(self, client, mock_catalogue): + def test_details_data_product_not_found(self, client, mock_catalogue): mock_catalogue.search.return_value = SearchResponse( total_results=0, page_results=[] ) - response = client.get(reverse("home:details", kwargs={"id": "fake"})) + response = client.get( + reverse( + "home:details", kwargs={"id": "fake", "result_type": "data_product"} + ) + ) assert response.status_code == 404 From d5b5ec209e85a56e15b9e3864620400b6dbf9d4f Mon Sep 17 00:00:00 2001 From: LavMatt Date: Wed, 21 Feb 2024 11:27:44 +0000 Subject: [PATCH 33/60] add selenium test for data product detail page --- tests/selenium/conftest.py | 12 ++++++++--- tests/selenium/test_search_scenarios.py | 27 ++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/tests/selenium/conftest.py b/tests/selenium/conftest.py index 2705904a..09bfec4e 100644 --- a/tests/selenium/conftest.py +++ b/tests/selenium/conftest.py @@ -67,10 +67,16 @@ def __init__(self, selenium): self.selenium = selenium -class DetailsPage(Page): +class DetailsDataProductPage(Page): def secondary_heading(self): return self.selenium.find_element(By.TAG_NAME, "h2") + def data_product_details(self): + return self.selenium.find_element(By.TAG_NAME, "dl") + + def data_product_tables(self): + return self.selenium.find_element(By.TAG_NAME, "table") + class HomePage(Page): def search_nav_link(self) -> WebElement: @@ -182,5 +188,5 @@ def search_page(selenium) -> SearchPage: @pytest.fixture -def details_page(selenium) -> DetailsPage: - return DetailsPage(selenium) +def details_data_product_page(selenium) -> DetailsDataProductPage: + return DetailsDataProductPage(selenium) diff --git a/tests/selenium/test_search_scenarios.py b/tests/selenium/test_search_scenarios.py index a6d972c2..4be4d9d6 100644 --- a/tests/selenium/test_search_scenarios.py +++ b/tests/selenium/test_search_scenarios.py @@ -13,12 +13,14 @@ class TestSearchWithoutJavascriptAndCss: """ @pytest.fixture(autouse=True) - def setup(self, live_server, selenium, home_page, search_page, details_page): + def setup( + self, live_server, selenium, home_page, search_page, details_data_product_page + ): self.selenium = selenium self.live_server_url = live_server.url self.home_page = home_page self.search_page = search_page - self.details_page = details_page + self.details_data_product_page = details_data_product_page def test_browse_to_first_item(self): """ @@ -155,6 +157,17 @@ def test_automated_accessibility_search(self): self.start_on_the_search_page() check_for_accessibility_issues(self.selenium.current_url) + def test_search_to_data_product_details(self): + """ + Users can search a data product and got to its details page + """ + self.start_on_the_search_page() + self.enter_a_query_and_submit("court timeliness data product") + item_name = self.click_on_the_first_result() + self.verify_i_am_on_the_details_page(item_name) + self.verify_data_product_details() + self.verify_data_product_tables_listed() + def start_on_the_home_page(self): self.selenium.get(f"{self.live_server_url}") assert "Data catalogue" in self.selenium.title @@ -189,7 +202,7 @@ def click_on_the_first_result(self): def verify_i_am_on_the_details_page(self, item_name): assert item_name in self.selenium.title - secondary_heading_text = self.details_page.secondary_heading().text + secondary_heading_text = self.details_data_product_page.secondary_heading().text assert secondary_heading_text == item_name @@ -245,3 +258,11 @@ def click_previous_page(self): def verify_sort_selected(self, expected): value = self.search_page.checked_sort_option().get_attribute("value") or "" assert value == expected.lower() + + def verify_data_product_tables_listed(self): + tables = self.details_data_product_page.data_product_tables() + assert tables.text + + def verify_data_product_details(self): + data_product_details = self.details_data_product_page.data_product_details() + assert data_product_details.text From 17f284aa5bf17e6d729a8c97d00f9a9e1cf693c2 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Wed, 21 Feb 2024 11:28:11 +0000 Subject: [PATCH 34/60] update poetry --- poetry.lock | 10 +++++----- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/poetry.lock b/poetry.lock index cc456ba1..c38f4dc1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "acryl-datahub" @@ -1894,14 +1894,14 @@ psutil = "*" [[package]] name = "ministryofjustice-data-platform-catalogue" -version = "0.10.0" +version = "0.15.0" description = "Library to integrate the MoJ data platform with the catalogue component." category = "main" optional = false python-versions = ">=3.10,<4.0" files = [ - {file = "ministryofjustice_data_platform_catalogue-0.10.0-py3-none-any.whl", hash = "sha256:6818d4be3d7e87f655ee125f89ca3cc797aa2d79bc77b04fe1ec7f656a2c2ac0"}, - {file = "ministryofjustice_data_platform_catalogue-0.10.0.tar.gz", hash = "sha256:1d052dcd97afed31daef37a185d48dbbd1aedfdb81fe03227c9aea07727ad772"}, + {file = "ministryofjustice_data_platform_catalogue-0.15.0-py3-none-any.whl", hash = "sha256:032c197b03050fa11197c991301678ea690abc7c08e18a88c141cd8e44436271"}, + {file = "ministryofjustice_data_platform_catalogue-0.15.0.tar.gz", hash = "sha256:0658d0f444c2f755d593ac0ce28afcb027239ed6b3c57bb2247f5d5c64485cfc"}, ] [package.dependencies] @@ -3865,4 +3865,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "a6499263725090cc0407852e9223b24a8c10269b11d75af9cdcbcf962809c7bb" +content-hash = "5ce756bb0eb9ff1946f3c628b3ac67572fdd742dea9980656080c9f689de1393" diff --git a/pyproject.toml b/pyproject.toml index b47e9f3c..b29b195c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ django = "^5.0.1" pyyaml = "^6.0.1" gunicorn = "^21.2.0" whitenoise = "^6.6.0" -ministryofjustice-data-platform-catalogue = "^0.10.0" +ministryofjustice-data-platform-catalogue = "^0.15.0" markdown = "^3.5.2" python-dotenv = "^1.0.1" From 4adb315f6d6c0cd865e6c793a33569ee73418ecd Mon Sep 17 00:00:00 2001 From: LavMatt Date: Fri, 23 Feb 2024 09:10:36 +0000 Subject: [PATCH 35/60] fix selenium tests that sometimes hit a dead end --- templates/partial/search_result.html | 4 ++-- tests/selenium/conftest.py | 8 ++++++++ tests/selenium/test_search_scenarios.py | 19 +++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/templates/partial/search_result.html b/templates/partial/search_result.html index 687ae625..eb97f27e 100644 --- a/templates/partial/search_result.html +++ b/templates/partial/search_result.html @@ -10,11 +10,11 @@

{{result.name}} {% endwith %} {% if result.result_type.name == "DATA_PRODUCT" %} - + Data product {% elif result.result_type.name == "TABLE" %} - + Table {% endif %} diff --git a/tests/selenium/conftest.py b/tests/selenium/conftest.py index 09bfec4e..d16e3539 100644 --- a/tests/selenium/conftest.py +++ b/tests/selenium/conftest.py @@ -108,6 +108,14 @@ def first_search_result(self) -> SearchResultWrapper: ) ) + def first_search_result_type(self) -> str: + return ( + self.selenium.find_element(By.ID, "search-results") + .find_element(By.CSS_SELECTOR, ".govuk-grid-row") + .find_element(By.ID, "result-type") + .text + ) + def search_bar(self) -> WebElement: return self.selenium.find_element(By.NAME, "query") diff --git a/tests/selenium/test_search_scenarios.py b/tests/selenium/test_search_scenarios.py index 4be4d9d6..34117d24 100644 --- a/tests/selenium/test_search_scenarios.py +++ b/tests/selenium/test_search_scenarios.py @@ -22,12 +22,16 @@ def setup( self.search_page = search_page self.details_data_product_page = details_data_product_page - def test_browse_to_first_item(self): + def test_browse_to_first_item_data_product(self): """ Browses from the home page -> search -> details page """ - self.start_on_the_home_page() - self.click_on_the_search_link() + while True: + self.start_on_the_home_page() + self.click_on_the_search_link() + result_type = self.get_search_first_result_type() + if result_type.lower() == "data product": + break self.verify_i_am_on_the_search_page() self.verify_i_have_results() @@ -162,12 +166,19 @@ def test_search_to_data_product_details(self): Users can search a data product and got to its details page """ self.start_on_the_search_page() - self.enter_a_query_and_submit("court timeliness data product") + while True: + self.enter_a_query_and_submit("court timeliness data product") + result_type = self.get_search_first_result_type() + if result_type.lower() == "data product": + break item_name = self.click_on_the_first_result() self.verify_i_am_on_the_details_page(item_name) self.verify_data_product_details() self.verify_data_product_tables_listed() + def get_search_first_result_type(self): + return self.search_page.first_search_result_type() + def start_on_the_home_page(self): self.selenium.get(f"{self.live_server_url}") assert "Data catalogue" in self.selenium.title From 875b88b13d8feac4505846ae2107bc048be9f852 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Fri, 23 Feb 2024 14:42:14 +0000 Subject: [PATCH 36/60] actually make the tests work for data product details --- tests/conftest.py | 13 +++------ tests/selenium/conftest.py | 15 +++------- tests/selenium/test_search_scenarios.py | 37 +++++++++++++------------ tests/test_services.py | 1 - 4 files changed, 28 insertions(+), 38 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 11fbf4e1..6b16df91 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,6 @@ import pytest from data_platform_catalogue.client import BaseCatalogueClient -from data_platform_catalogue.client.datahub.datahub_client import DataHubCatalogueClient from data_platform_catalogue.search_types import ( FacetOption, ResultType, @@ -15,7 +14,7 @@ from faker import Faker from home.forms.search import SearchForm -from home.service.details import DetailsDataProductService +from home.service.details import DataProductDetailsService from home.service.search import SearchService from datahub.metadata.schema_classes import ( @@ -86,7 +85,7 @@ def mock_catalogue(): page_results=generate_page(page_size=1, result_type=ResultType.TABLE), total_results=1, ) - # mock_get_dataproduct_aspect(mock_catalogue) + yield mock_catalogue patcher.stop() @@ -136,11 +135,7 @@ def detail_dataproduct_context(mock_catalogue): mock_catalogue.search.return_value = SearchResponse( total_results=1, page_results=generate_page(page_size=1) ) - # mock_catalogue.list_data_product_assets.return_value = SearchResponse( - # total_results=1, - # page_results=generate_page(page_size=1, result_type=ResultType.TABLE), - # ) - # with patch(): - details_service = DetailsDataProductService(urn="urn:li:dataProduct:test") + + details_service = DataProductDetailsService(urn="urn:li:dataProduct:test") context = details_service._get_context() return context diff --git a/tests/selenium/conftest.py b/tests/selenium/conftest.py index d16e3539..a35c6844 100644 --- a/tests/selenium/conftest.py +++ b/tests/selenium/conftest.py @@ -11,6 +11,7 @@ from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.select import Select + TMP_DIR = Path(__file__).parent / "../../tmp" @@ -67,7 +68,7 @@ def __init__(self, selenium): self.selenium = selenium -class DetailsDataProductPage(Page): +class DataProductDetailsPage(Page): def secondary_heading(self): return self.selenium.find_element(By.TAG_NAME, "h2") @@ -108,14 +109,6 @@ def first_search_result(self) -> SearchResultWrapper: ) ) - def first_search_result_type(self) -> str: - return ( - self.selenium.find_element(By.ID, "search-results") - .find_element(By.CSS_SELECTOR, ".govuk-grid-row") - .find_element(By.ID, "result-type") - .text - ) - def search_bar(self) -> WebElement: return self.selenium.find_element(By.NAME, "query") @@ -196,5 +189,5 @@ def search_page(selenium) -> SearchPage: @pytest.fixture -def details_data_product_page(selenium) -> DetailsDataProductPage: - return DetailsDataProductPage(selenium) +def details_data_product_page(selenium) -> DataProductDetailsPage: + return DataProductDetailsPage(selenium) diff --git a/tests/selenium/test_search_scenarios.py b/tests/selenium/test_search_scenarios.py index 34117d24..c8f427e8 100644 --- a/tests/selenium/test_search_scenarios.py +++ b/tests/selenium/test_search_scenarios.py @@ -3,6 +3,8 @@ import pytest from .helpers import check_for_accessibility_issues +from tests.conftest import mock_search_response, generate_page +from data_platform_catalogue.search_types import ResultType @pytest.mark.slow @@ -22,19 +24,22 @@ def setup( self.search_page = search_page self.details_data_product_page = details_data_product_page - def test_browse_to_first_item_data_product(self): + def test_browse_to_first_item_data_product(self, mock_catalogue): """ Browses from the home page -> search -> details page """ - while True: - self.start_on_the_home_page() - self.click_on_the_search_link() - result_type = self.get_search_first_result_type() - if result_type.lower() == "data product": - break + # we need to mock search response to be data products + mock_search_response( + mock_catalogue=mock_catalogue, + page_results=generate_page(result_type=ResultType.DATA_PRODUCT), + total_results=100, + ) + + self.start_on_the_home_page() + self.click_on_the_search_link() + self.verify_i_am_on_the_search_page() self.verify_i_have_results() - item_name = self.click_on_the_first_result() self.verify_i_am_on_the_details_page(item_name) @@ -161,24 +166,22 @@ def test_automated_accessibility_search(self): self.start_on_the_search_page() check_for_accessibility_issues(self.selenium.current_url) - def test_search_to_data_product_details(self): + def test_search_to_data_product_details(self, mock_catalogue): """ Users can search a data product and got to its details page """ + mock_search_response( + mock_catalogue=mock_catalogue, + page_results=generate_page(result_type=ResultType.DATA_PRODUCT), + total_results=100, + ) self.start_on_the_search_page() - while True: - self.enter_a_query_and_submit("court timeliness data product") - result_type = self.get_search_first_result_type() - if result_type.lower() == "data product": - break + self.enter_a_query_and_submit("court timeliness") item_name = self.click_on_the_first_result() self.verify_i_am_on_the_details_page(item_name) self.verify_data_product_details() self.verify_data_product_tables_listed() - def get_search_first_result_type(self): - return self.search_page.first_search_result_type() - def start_on_the_home_page(self): self.selenium.get(f"{self.live_server_url}") assert "Data catalogue" in self.selenium.title diff --git a/tests/test_services.py b/tests/test_services.py index 7122bda2..75f1015c 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -3,7 +3,6 @@ import pytest from data_platform_catalogue.search_types import ResultType from home.service.search import SearchForm, SearchService -from unittest.mock import patch from home.service.search import domains_with_their_subdomains From 779a7af93489b3de0322227b506165e00fbc29fc Mon Sep 17 00:00:00 2001 From: LavMatt Date: Fri, 23 Feb 2024 14:42:49 +0000 Subject: [PATCH 37/60] this template will always be data product and align case --- templates/details_data_product.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/details_data_product.html b/templates/details_data_product.html index b30ad60b..26ec9e62 100644 --- a/templates/details_data_product.html +++ b/templates/details_data_product.html @@ -9,7 +9,7 @@ Back
- {{result_type}} + Data product

{{result.name}}

@@ -82,7 +82,7 @@

{{result.name}}


- + From cc74fd626cb7b8771f3843547b19196f51a19c37 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Fri, 23 Feb 2024 14:44:10 +0000 Subject: [PATCH 38/60] rename view, service and add blank dataset template --- home/service/details.py | 10 +++++++++- home/urls.py | 2 +- home/views.py | 20 ++++++++++++++++---- templates/details_dataset.html | 1 + 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 templates/details_dataset.html diff --git a/home/service/details.py b/home/service/details.py index b7f79009..5a5fa9f6 100644 --- a/home/service/details.py +++ b/home/service/details.py @@ -5,7 +5,7 @@ from .base import GenericService -class DetailsDataProductService(GenericService): +class DataProductDetailsService(GenericService): def __init__(self, urn: str): self.urn = urn self.client = self._get_catalogue_client() @@ -62,3 +62,11 @@ def _get_context(self): } return context + + +class DatasetDetailsService(GenericService): + def __init__(self, urn: str): + self.context = self._get_context() + + def _get_context(self): + return {} diff --git a/home/urls.py b/home/urls.py index 722cc492..7149e8bf 100644 --- a/home/urls.py +++ b/home/urls.py @@ -9,7 +9,7 @@ path("search", views.search_view, name="search"), path( "details//", - views.redirect_details_view, + views.details_view, name="details", ), path("pagination/", views.search_view, name="pagination"), diff --git a/home/views.py b/home/views.py index 565ae2cb..4be2b8be 100644 --- a/home/views.py +++ b/home/views.py @@ -3,7 +3,7 @@ from django.shortcuts import render from home.forms.search import SearchForm -from home.service.details import DetailsDataProductService +from home.service.details import DataProductDetailsService, DatasetDetailsService from home.service.search import SearchService @@ -12,17 +12,29 @@ def home_view(request): return render(request, "home.html", context) -def redirect_details_view(request, result_type, id): +def details_view(request, result_type, id): if result_type == "data_product": context = data_product_details(request, id) return render(request, "details_data_product.html", context) if result_type == "table": - pass + context = dataset_details(request, id) + return render(request, "details_dataset.html", context) def data_product_details(request, id): try: - service = DetailsDataProductService(id) + service = DataProductDetailsService(id) + except ObjectDoesNotExist: + raise Http404("Asset does not exist") + + context = service.context + + return context + + +def dataset_details(request, id): + try: + service = DatasetDetailsService(id) except ObjectDoesNotExist: raise Http404("Asset does not exist") diff --git a/templates/details_dataset.html b/templates/details_dataset.html new file mode 100644 index 00000000..30404ce4 --- /dev/null +++ b/templates/details_dataset.html @@ -0,0 +1 @@ +TODO \ No newline at end of file From b987082736530647079ff672dad2067ccb98b52b Mon Sep 17 00:00:00 2001 From: LavMatt Date: Fri, 23 Feb 2024 14:54:51 +0000 Subject: [PATCH 39/60] markdown and trim for table descriptions in data product detail page --- templates/details_data_product.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/templates/details_data_product.html b/templates/details_data_product.html index 26ec9e62..aacab300 100644 --- a/templates/details_data_product.html +++ b/templates/details_data_product.html @@ -95,7 +95,13 @@

{{result.name}}

{% with table_type=table.type|lower %}
- + {% endwith %} From 36ba9e5580324575021239282e7aaa761e7291ab Mon Sep 17 00:00:00 2001 From: LavMatt Date: Fri, 23 Feb 2024 14:58:48 +0000 Subject: [PATCH 40/60] remove self.data_product_name from dataproductservice --- home/service/details.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/home/service/details.py b/home/service/details.py index 5a5fa9f6..31cdccaf 100644 --- a/home/service/details.py +++ b/home/service/details.py @@ -17,7 +17,6 @@ def __init__(self, urn: str): raise ObjectDoesNotExist(urn) self.result = search_results.page_results[0] - self.data_product_name = self.result.name self.assets_in_data_product = self._get_data_product_entities() self.context = self._get_context() @@ -36,7 +35,7 @@ def _get_data_product_entities(self): { "name": ( result.name - if not result.name.split(".")[0] == self.data_product_name + if not result.name.split(".")[0] == self.result.name else result.name.split(".")[1] ), "urn": result.id, From 2a373879818b4ce077cc78a881ac165b1717d94f Mon Sep 17 00:00:00 2001 From: LavMatt Date: Mon, 26 Feb 2024 09:01:09 +0000 Subject: [PATCH 41/60] try reinstalling deps for selenium tests --- .github/workflows/test.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eec7b7e3..ac51b498 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,15 +27,7 @@ jobs: version: 1.7.1 virtualenvs-create: true virtualenvs-in-project: true - - name: cache deps - id: cache-deps - uses: actions/cache@v2 - with: - path: .venv - key: pydeps-${{ hashFiles('**/poetry.lock') }} - run: poetry install --no-interaction --no-root - if: steps.cache-deps.outputs.cache-hit != 'true' - - run: poetry install --no-interaction - name: run unit tests with coverage id: fast-tests run: poetry run pytest --cov -m 'not slow' From f853f7a34860fdba2aed4c03f80b54556087fce7 Mon Sep 17 00:00:00 2001 From: LavMatt Date: Mon, 26 Feb 2024 09:25:43 +0000 Subject: [PATCH 42/60] revert workflow change --- .github/workflows/test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac51b498..eec7b7e3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,15 @@ jobs: version: 1.7.1 virtualenvs-create: true virtualenvs-in-project: true + - name: cache deps + id: cache-deps + uses: actions/cache@v2 + with: + path: .venv + key: pydeps-${{ hashFiles('**/poetry.lock') }} - run: poetry install --no-interaction --no-root + if: steps.cache-deps.outputs.cache-hit != 'true' + - run: poetry install --no-interaction - name: run unit tests with coverage id: fast-tests run: poetry run pytest --cov -m 'not slow' From 5b24a2c8f07984ccf6439ff2c91db7a5690bab99 Mon Sep 17 00:00:00 2001 From: Mat Moore Date: Tue, 20 Feb 2024 17:13:46 +0000 Subject: [PATCH 43/60] Add javascript for domain filter widget Domain will have top level and subdomain selections, and work similarly to "Topic/Sub-Topic" on GOV.UK search. The form will submit domain and subdomain as separate fields, so we need to combine them on the backend. If javascript is not enabled, then the subdomain field is not displayed and it will work as before. This is tested using jest and jest-dom. --- .github/workflows/test.yml | 30 + .gitignore | 2 + README.md | 3 +- babel.config.js | 1 + jest.config.js | 195 ++ package-lock.json | 2745 +++++++++++++++++----- package.json | 10 +- scss/base.scss | 4 + static/assets/css/base.css | 4 + static/assets/css/base.css.map | 2 +- static/assets/js/enhanced-search.js | 138 ++ templates/base/base.html | 4 +- templates/search.html | 6 + tests/javascript/jest-setup.js | 1 + tests/javascript/test_enhanced_search.js | 166 ++ 15 files changed, 2681 insertions(+), 630 deletions(-) create mode 100644 babel.config.js create mode 100644 jest.config.js create mode 100644 static/assets/js/enhanced-search.js create mode 100644 tests/javascript/jest-setup.js create mode 100644 tests/javascript/test_enhanced_search.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eec7b7e3..5f3441ea 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,37 @@ jobs: - name: run unit tests with coverage id: fast-tests run: poetry run pytest --cov -m 'not slow' + - name: run selenium tests id: slow-tests if: steps.fast-tests.outcome == 'success' run: poetry run pytest -m 'slow' + + test_javascript: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: "21" + + - name: Get npm cache directory + id: npm-cache-dir + shell: bash + run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT} + + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + id: install_dependencies + run: npm install + + - name: Run javascript tests + run: npm test diff --git a/.gitignore b/.gitignore index 3fc08e87..48c5d70b 100644 --- a/.gitignore +++ b/.gitignore @@ -166,3 +166,5 @@ staticfiles/ node_modules tmp/ + +coverage diff --git a/README.md b/README.md index 552f5c7d..f72bfe5e 100644 --- a/README.md +++ b/README.md @@ -28,5 +28,6 @@ Run `pre-commit install` from inside the poetry environment to set up pre commit ## Testing -- Unit tests: `pytest -m 'not slow'` +- Python unit tests: `pytest -m 'not slow'` +- Javascript unit tests: `npm test` - Selenium tests: `pytest -m 'slow'` diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..721e8b82 --- /dev/null +++ b/babel.config.js @@ -0,0 +1 @@ +module.exports = { presets: ["@babel/preset-env"] }; diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..9f957fbf --- /dev/null +++ b/jest.config.js @@ -0,0 +1,195 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +/** @type {import('jest').Config} */ +const config = { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/private/var/folders/lh/0dtbp3254mvc5pvhcx4ngnf80000gq/T/jest_dz", + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + moduleDirectories: ["node_modules", "static/assets/js"], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: undefined, + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + setupFilesAfterEnv: ["/tests/javascript/jest-setup.js"], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "jsdom", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + testMatch: ["**/?(*.)+(spec|test).[tj]s?(x)", "**/test_*.[tj]s?(x)"], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "/node_modules/" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + transform: { + "\\.[jt]sx?$": "babel-jest", + }, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; + +module.exports = config; diff --git a/package-lock.json b/package-lock.json index c4e4384b..e5cc3a01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,10 +5,2094 @@ "packages": { "": { "dependencies": { + "@babel/preset-env": "^7.23.9", "@ministryofjustice/frontend": "^2.1.0", - "axe": "^12.2.3", "govuk-frontend": "^5.1.0", + "jest-environment-jsdom": "^29.7.0", "sass": "^1.70.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.4.2", + "jest": "^29.7.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.23.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz", + "integrity": "sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "dependencies": { + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "dependencies": { + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", + "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", + "dependencies": { + "@babel/compat-data": "^7.23.3", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.23.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", + "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.9", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.9", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@babel/code-frame": { @@ -64,38 +2148,6 @@ "jquery": "^3.6.0" } }, - "node_modules/@strikeentco/get": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@strikeentco/get/-/get-1.0.1.tgz", - "integrity": "sha512-qPnoWkt7xxcOaUJhMveDHmj6INVKHXUEsPTGz3g4HC5XNnqRd1dDEFxL1KpG+vZ2VxmRK42EjBt5vUDr4uLzQQ==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@strikeentco/set": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@strikeentco/set/-/set-1.0.2.tgz", - "integrity": "sha512-jP/wGhBi70RoD2Ww2bd3Ay4nzKfyWSPL/sDgFaq2e/FXNC9a04R0M7fuDVHG/dG+WWNVj2pmE9exXn20a0AjGg==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -108,30 +2160,6 @@ "node": ">= 8" } }, - "node_modules/axe": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/axe/-/axe-12.2.3.tgz", - "integrity": "sha512-ZZ1kJi7ygeMPoVUgIkFcFbN+Wr/gYusdDWkBZNxu6ZMxAaTE3vnfLHeDR+1TQSZBE0l3qpqKKHHef2FRz8N83g==", - "dependencies": { - "@ladjs/format-util": "^1.0.4", - "@strikeentco/get": "1.0.1", - "@strikeentco/set": "1.0.2", - "boolean": "3.2.0", - "console-polyfill": "0.3.0", - "format-specifiers": "^1.0.0", - "is-symbol": "^1.0.4", - "iserror": "0.0.2", - "merge-options": "3.0.4", - "p-map-series": "2", - "parse-app-info": "^5.0.0", - "parse-err": "^1.0.0", - "pick-deep": "1.0.0", - "unset-value": "2.0.1" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -140,11 +2168,6 @@ "node": ">=8" } }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" - }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -156,19 +2179,6 @@ "node": ">=8" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -184,57 +2194,15 @@ "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/console-polyfill": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/console-polyfill/-/console-polyfill-0.3.0.tgz", - "integrity": "sha512-w+JSDZS7XML43Xnwo2x5O5vxB0ID7T5BdqDtyqT6uiCAX2kZAgcWxNaGqT97tZfSHzfOcvrfsDAodKcJ3UvnXQ==" - }, - "node_modules/dotgitconfig": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/dotgitconfig/-/dotgitconfig-1.1.2.tgz", - "integrity": "sha512-M+nUsYHJT2qs6bnYqotmO+1IQ09w3ZwLcX4MmbblaWN9C7ydDWM2xQLv22xfl4bUxienESi1GsZnZJPb8jslqQ==", - "dependencies": { - "ini": "^1.3.5" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=0.8.0" + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/fill-range": { @@ -248,23 +2216,6 @@ "node": ">=8" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/format-specifiers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/format-specifiers/-/format-specifiers-1.0.0.tgz", - "integrity": "sha512-/xcmy6xn/DsR+V6flFj3E47yCbrsk70r90moAMENVkKckUPUG9CRE79S/2xajLVx1iADIoWx+1R304uMXB/riQ==" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -278,33 +2229,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-value": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-3.0.1.tgz", - "integrity": "sha512-mKZj9JLQrwMBtj5wxi6MH8Z5eSKaERpAwjg43dPtlGI1ZVEgH/qC7T8/6R2OBSUA+zzHBZgICsVJaEIV2tKTDA==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/get-value/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -316,6 +2240,14 @@ "node": ">= 6" } }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, "node_modules/govuk-frontend": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.1.0.tgz", @@ -324,84 +2256,11 @@ "node": ">= 4.2.0" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-value": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-2.0.2.tgz", - "integrity": "sha512-ybKOlcRsK2MqrM3Hmz/lQxXHZ6ejzSPzpNabKB45jb5qDgJvKPa3SdapTsTLwEb9WltgWpOmNax7i+DzNOk4TA==", - "dependencies": { - "get-value": "^3.0.0", - "has-values": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-values": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-2.0.1.tgz", - "integrity": "sha512-+QdH3jOmq9P8GfdjFg0eJudqx1FqU62NQJ4P16rOEHeRdl7ckgwn6uqQjzYE0ZoHVV/e5E2esuJ5Gl5+HUW19w==", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" - }, "node_modules/immutable": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/ip": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", - "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -432,6 +2291,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -451,116 +2328,12 @@ "node": ">=0.12.0" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/iserror": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/iserror/-/iserror-0.0.2.tgz", - "integrity": "sha512-oKGGrFVaWwETimP3SiWwjDeY27ovZoyZPHtxblC4hCq9fXxed/jasx+ATWFFjCVSRZng8VTMsN1nDnGo6zMBSw==" - }, - "node_modules/isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jquery": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", "peer": true }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/last-commit-log": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/last-commit-log/-/last-commit-log-3.3.0.tgz", - "integrity": "sha512-qYzhTltQvQ/mMIDWnG16KyUi79y4F5uEqHDDbAJm2HLuWgDuBhZ8g5PyWomYV0wsDQDuYcPWMQdJ91wsZOZ5NQ==", - "dependencies": { - "dotgitconfig": "^1.1.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-options": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", - "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", - "dependencies": { - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -569,25 +2342,6 @@ "node": "*" } }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -596,115 +2350,6 @@ "node": ">=0.10.0" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-2.1.0.tgz", - "integrity": "sha512-RpYIIK1zXSNEOdwxcfe7FdvGcs7+y5n8rifMhMNWvaxRNMPINJHF5GDeuVxWqnfrcHPSCnp7Oo5yNXHId9Av2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-app-info": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-app-info/-/parse-app-info-5.0.0.tgz", - "integrity": "sha512-uP4Bcso/FvnPpPmO5iPszdf0HoqugxoYjXxnosL6XBxR8gRl78NJdKoRxrsTESeYQv4qN4jThPsCxdmEzpIZ5g==", - "dependencies": { - "ip": "^1.1.8", - "last-commit-log": "^3.3.0", - "lodash": "^4.17.21", - "read-pkg-up": "7", - "semver": "^7.5.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/parse-err": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-err/-/parse-err-1.0.0.tgz", - "integrity": "sha512-K2RCrbPe7CXezMfRQTZJgCOQB6kyUofAkEriwGfaP4oiwbRm3YDTG6F8qEBSFVA7QiLzph/rMqokPcOz26UxSw==", - "dependencies": { - "iserror": "^0.0.2" - }, - "engines": { - "node": ">=6.4.0" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/pick-deep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pick-deep/-/pick-deep-1.0.0.tgz", - "integrity": "sha512-Uy0VUtabou1sPl/vVClBFrWi4Ae/D3Vqu44FJawmm4lnduu5E16ykw8kh15fiUeLQ6lbmXQ0EMr3YIsqpLZl+A==", - "dependencies": { - "@strikeentco/get": "^1.0.0", - "@strikeentco/set": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -716,44 +2361,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "engines": { - "node": ">=8" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -765,22 +2372,6 @@ "node": ">=8.10.0" } }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/sass": { "version": "1.70.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", @@ -797,20 +2388,6 @@ "node": ">=14.0.0" } }, - "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -819,56 +2396,6 @@ "node": ">=0.10.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -879,40 +2406,6 @@ "engines": { "node": ">=8.0" } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/unset-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-2.0.1.tgz", - "integrity": "sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg==", - "dependencies": { - "has-value": "^2.0.2", - "isobject": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index 742b72b6..33321117 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,19 @@ { "dependencies": { + "@babel/preset-env": "^7.23.9", "@ministryofjustice/frontend": "^2.1.0", + "babel-jest": "^29.7.0", "axe": "^12.2.3", "govuk-frontend": "^5.1.0", + "jest-environment-jsdom": "^29.7.0", "sass": "^1.70.0" }, "scripts": { - "sass": "sass --load-path=. scss:static/assets/css" + "sass": "sass --load-path=. scss:static/assets/css", + "test": "jest" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.4.2", + "jest": "^29.7.0" } } diff --git a/scss/base.scss b/scss/base.scss index 0299b1c1..6d56595c 100644 --- a/scss/base.scss +++ b/scss/base.scss @@ -6,3 +6,7 @@ $govuk-global-styles: true; @import "node_modules/govuk-frontend/dist/govuk/all"; @import "node_modules/@ministryofjustice/frontend/moj/all"; + +.js-required { + display: none; +} \ No newline at end of file diff --git a/static/assets/css/base.css b/static/assets/css/base.css index d21d1767..75f62312 100644 --- a/static/assets/css/base.css +++ b/static/assets/css/base.css @@ -10837,4 +10837,8 @@ span.moj-header__link:hover { } } +.js-required { + display: none; +} + /*# sourceMappingURL=base.css.map */ diff --git a/static/assets/css/base.css.map b/static/assets/css/base.css.map index 6446a3e0..8827ced8 100644 --- a/static/assets/css/base.css.map +++ b/static/assets/css/base.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../../../node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_links.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_typography.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_typography-font.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_links.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_links.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_font-faces.scss","../../../node_modules/govuk-frontend/dist/govuk/vendor/_sass-mq.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_focused.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_colours-applied.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_lists.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_spacing.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_typography.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_section-break.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_button-group.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_form-group.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_clearfix.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_grid.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_grid.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_main-wrapper.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_template.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_width-container.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_measurements.scss","../../../node_modules/govuk-frontend/dist/govuk/components/accordion/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/back-link/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/button/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/error-message/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/hint/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/label/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/textarea/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/fieldset/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/checkboxes/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/input/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/date-input/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/details/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_shape-arrow.scss","../../../node_modules/govuk-frontend/dist/govuk/components/error-summary/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/exit-this-page/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_device-pixels.scss","../../../node_modules/govuk-frontend/dist/govuk/components/header/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/inset-text/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/notification-banner/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/pagination/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/panel/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/tag/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/phase-banner/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/radios/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/select/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/skip-link/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_visually-hidden.scss","../../../node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/table/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/tabs/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/task-list/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/utilities/_visually-hidden.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_display.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_spacing.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_text-align.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_typography.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_width.scss","../../../node_modules/@ministryofjustice/frontend/moj/settings/_assets.scss","../../../node_modules/@ministryofjustice/frontend/moj/settings/_measurements.scss","../../../node_modules/@ministryofjustice/frontend/moj/settings/_colours.scss","../../../node_modules/@ministryofjustice/frontend/moj/objects/_filter-layout.scss","../../../node_modules/@ministryofjustice/frontend/moj/objects/_scrollable-pane.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/action-bar/_action-bar.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/add-another/_add-another.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/badge/_badge.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/banner/_banner.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/button-menu/_button-menu.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/cookie-banner/_cookie-banner.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/currency-input/_currency-input.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/filter/_filter.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/header/_header.scss","../../../node_modules/@ministryofjustice/frontend/moj/objects/_width-container.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/identity-bar/_identity-bar.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/messages/_messages.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/multi-file-upload/_multi-file-upload.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/multi-select/_multi-select.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/notification-badge/_notification-badge.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/organisation-switcher/_organisation-switcher.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/page-header-actions/_page-header-actions.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/pagination/_pagination.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/password-reveal/_password-reveal.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/primary-navigation/_primary-navigation.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/progress-bar/_progress-bar.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/rich-text-editor/_rich-text-editor.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/search-toggle/search-toggle.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/search/_search.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/side-navigation/_side-navigation.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/sortable-table/_sortable-table.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/sub-navigation/_sub-navigation.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/tag/_tag.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/task-list/_task-list.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/timeline/_timeline.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/ticket-panel/_ticket-panel.scss","../../../node_modules/@ministryofjustice/frontend/moj/utilities/_hidden.scss","../../../node_modules/@ministryofjustice/frontend/moj/helpers/_hidden.scss","../../../node_modules/@ministryofjustice/frontend/moj/utilities/_width-container.scss"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;EAGE;EAIE;EAAA;EAAA;;;;ACNF;ECcA,aCFkB;EDGlB;EACA;EEaA;EAGE,2BChB6B;EDoB7B,uBCP0B;;ACdxB;AACA;EACE;EACA;EACA;EACA,KACE;EAEF;;AAGF;EACE;EACA;EACA;EACA,KACE;EAEF;;ACkMA;ENnON;ICyBE,aCHsB;;;ACTxB;EAqCE,2BCLmC;EDQnC;EACQ;EACR;EACQ;;AAvCV;EIFA;EACA,OC4DwB;ED3DxB,kBCiDmB;EDhDnB,YACE;EAIF;EAIA;EACQ;;AJgDR;EACE,OKuDgB;;ALpDlB;EACE,OK0DwB;;ALvD1B;EACE,OK6DsB;;AL1DxB;EACE,OKgEuB;;AL3DzB;EACE,OKnBsB;;AFuJlB;EH+HF;IACE;IACA;IAKA;;;;AA3KN;EAEE,OKxI0B;;AL2I5B;EAEE,OKhLgB;;ALqLlB;EACE,OK/HsB;;;ALoJxB;EF5LA,OOfkB;;AF8MZ;EHHN;IFzLE,OOQsB;;;ALwLxB;EAEI;;AAIJ;EFzMA,OOfkB;;AF8MZ;EHUN;IFtME,OOQsB;;;;ALqNxB;EAEE;;AAKF;EAEE;;AAGF;EACE,OKrMsB;;;ALoQxB;EACE;;;AAvCF;EACE,OKvKgB;;AL0KlB;EACE,OK3KgB;;AL8KlB;EACE,OKjKsB;;ALoKxB;EACE,OK9JuB;;ALmKzB;EACE,OKjPsB;;;ARzCxB;EGqVA;EAGA;EAGA;;AAEA;EIvVA;EACA,YACE;;;;AE3CF;ERcA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EApL3B,OOfkB;EClBhB;ECsGI;EDpGJ;EACA;;AH6NI;EGnON;IRyBE,aCHsB;;;AI6MlB;EGnON;IRoOM,WAbY;IAcZ,aAbqB;;;AKWrB;EGnON;IR+NM,WATQ;IAUR,aARqB;;;AKWrB;EGnON;IRuCE,OOQsB;;;AFoLlB;EGnON;ICgHQ;;;ADvGN;EACE;;;AAIJ;EAIE;;;AAOF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;;AH8LI;EGhMN;AAAA;IAKI;;;;AAIJ;EACE;;AHsLI;EGvLN;IAII;;;;;AE9CJ;EVkCA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUlNzB;EAEA;EDiGI;;AJ0HA;EKjON;IVqCE,OOQsB;;;AFoLlB;EKjON;IVuBE,aCHsB;;;AI6MlB;EKjON;IVkOM,WAbY;IAcZ,aAbqB;;;AKWrB;EKjON;IV6NM,WATQ;IAUR,aARqB;;;AKWrB;EKjON;ID8GQ;;;;AChGR;EVoBA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUpMzB;EAEA;EDmFI;;AJ0HA;EKnNN;IVuBE,OOQsB;;;AFoLlB;EKnNN;IVSE,aCHsB;;;AI6MlB;EKnNN;IVoNM,WAbY;IAcZ,aAbqB;;;AKWrB;EKnNN;IV+MM,WATQ;IAUR,aARqB;;;AKWrB;EKnNN;IDgGQ;;;;AClFR;EVMA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUtLzB;EAEA;EDqEI;;AJ0HA;EKrMN;IVSE,OOQsB;;;AFoLlB;EKrMN;IVLE,aCHsB;;;AI6MlB;EKrMN;IVsMM,WAbY;IAcZ,aAbqB;;;AKWrB;EKrMN;IViMM,WATQ;IAUR,aARqB;;;AKWrB;EKrMN;IDkFQ;;;;ACpER;EVRA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUxKzB;EAEA;EDuDI;;AJ0HA;EKvLN;IVLE,OOQsB;;;AFoLlB;EKvLN;IVnBE,aCHsB;;;AI6MlB;EKvLN;IVwLM,WAbY;IAcZ,aAbqB;;;AKWrB;EKvLN;IVmLM,WATQ;IAUR,aARqB;;;AKWrB;EKvLN;IDoEQ;;;;ACpDR;EV9CA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUzJzB;EAEA;EAEA,OHX0B;;AF2KtB;EKvKN;IVnCE,aCHsB;;;AI6MlB;EKvKN;IVwKM,WAbY;IAcZ,aAbqB;;;AKWrB;EKvKN;IVmKM,WATQ;IAUR,aARqB;;;;AUlJ3B;EVxDA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EU/IzB;EAEA;EACA,OHpB0B;;AF2KtB;EK7JN;IV7CE,aCHsB;;;AI6MlB;EK7JN;IV8JM,WAbY;IAcZ,aAbqB;;;AKWrB;EK7JN;IVyJM,WATQ;IAUR,aARqB;;;AKWrB;EK7JN;IASI;;;;AAIJ;EVrEA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUlIzB;EAEA,OHhC0B;;AF2KtB;EKhJN;IV1DE,aCHsB;;;AI6MlB;EKhJN;IViJM,WAbY;IAcZ,aAbqB;;;AKWrB;EKhJN;IV4IM,WATQ;IAUR,aARqB;;;;AU3H3B;EVzDA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUvHzB;EDQI;;AJ0HA;EKtIN;IVtDE,OOQsB;;;AFoLlB;EKtIN;IVpEE,aCHsB;;;AI6MlB;EKtIN;IVuIM,WAbY;IAcZ,aAbqB;;;AKWrB;EKtIN;IVkIM,WATQ;IAUR,aARqB;;;AKWrB;EKtIN;IDmBQ;;;;ACPR;EVrEA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EU3GzB;EDJI;;AJ0HA;EK1HN;IVlEE,OOQsB;;;AFoLlB;EK1HN;IVhFE,aCHsB;;;AI6MlB;EK1HN;IV2HM,WAbY;IAcZ,aAbqB;;;AKWrB;EK1HN;IVsHM,WATQ;IAUR,aARqB;;;AKWrB;EK1HN;IDOQ;;;;ACKR;EVjFA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EU/FzB;EDhBI;;AJ0HA;EK9GN;IV9EE,OOQsB;;;AFoLlB;EK9GN;IV5FE,aCHsB;;;AI6MlB;EK9GN;IV+GM,WAbY;IAcZ,aAbqB;;;AKWrB;EK9GN;IV0GM,WATQ;IAUR,aARqB;;;AKWrB;EK9GN;IDLQ;;;;ACkBR;EV9FA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUlFzB;ED7BI;;AJ0HA;EKjGN;IV3FE,OOQsB;;;AFoLlB;EKjGN;IVzGE,aCHsB;;;AI6MlB;EKjGN;IVkGM,WAbY;IAcZ,aAbqB;;;AKWrB;EKjGN;IV6FM,WATQ;IAUR,aARqB;;;AKWrB;EKjGN;IDlBQ;;;;AC+CR;EACE;;ALmEI;EKpEN;IAII;;;;AAIJ;AAAA;AAAA;ED9DM;;AJ0HA;EK5DN;AAAA;AAAA;IDvDQ;;;;AC6DR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;ALgDI;EKtDN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;IASI;;;;;ACtLJ;EACE;EACA;;;AASF;EF8FM;EAAA;;AJ0HA;EMxNN;IFqGQ;;;AJmHF;EMxNN;IFqGQ;;;;AE5FR;EFqFM;EAAA;;AJ0HA;EM/MN;IF4FQ;;;AJmHF;EM/MN;IF4FQ;;;;AEnFR;EF4EM;EAAA;;AJ0HA;EMtMN;IFmFQ;;;AJmHF;EMtMN;IFmFQ;;;;AExER;EACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/BF;EH+FM;EG3EJ;EACA;EACA;;APmMI;EOzNN;IHsGQ;;;AGzEN;EZzBF,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EY/KvB;EAGA;EACA,YA3Ba;EA4Bb;EACA;;APoLE;EO5LJ;IZdA,aCHsB;;;AI6MlB;EO5LJ;IZ6LI,WAbY;IAcZ,aAbqB;;;AKWrB;EO5LJ;IZwLI,WATQ;IAUR,aARqB;;;AYpKzB;EACE;;AP8KE;EOzNN;IAkDI;IAEA;IACA;IACA;;EAEA;AAAA;IAEE,cAzDa;;EA4Df;IACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtEN;EJuGM;;AKjGN;EACE;EACA;EACA;;ATwNI;EQjON;IJ8GQ;;;AI1GN;EACE;;;AAIJ;EACE;EACA;;AAEA;EAEE;EACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEhBJ;EAEE;EACA;;ADGF;EACE;EACA;EACA;;;ACFA;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1B7C;EAIE;EACA;EACA;;AZsMI;EY5MN;IAYI;IACA;;;;AAWJ;AAAA;ER0DM;;AJ0HA;EYpLN;AAAA;IRiEQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AS7GR;EAGE,kBXyB6B;EWrB7B;EACG;EACK;;AAcR;EAvBF;IAwBI;;EAEA;IACE;;;AbqMA;EahON;IAkCI;;;;AAKJ;EAGE;EAEA,kBXT2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AYgC7B;EAlDA,WCRiB;EDWjB,cC2BkB;ED1BlB,aC0BkB;;ADvBlB;EA2CA;IArCE;IACA;;;AdiMI;Ec7JN;IA/BE,cCIW;IDHX,aCGW;;EDAX;IA2BF;MArBI;MACA;;;;AdiLE;Ec7JN;IAbE;IACA;;EAIA;IAQF;MAPI;MACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AE3DJ;EZoGM;;AJ0HA;EgB9NN;IZ2GQ;;;;AYvGR;EACE;;;AAGF;EAEE;EACA;EAEA;EACA;;;AAGF;ErBRA,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EApL3B,OOfkB;EcKhB;EACA;EACA;;AhBuMI;EgB7MN;IrBGE,aCHs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;;;AKWrB;EuCnON;InCgHQ;;;AmCxGN;EACE;;;AAIJ;EACE;EAGA;;AvCkNI;EuCtNN;IAOI;;;;AAIJ;E5CmMI,WAJc;EAKd,aAJuB;EA5J3B;E4C/BE;EACA;EACA;;AvCoMI;EuC3MN;I5C4MM,WAbY;IAcZ,aAbqB;;;AKWrB;EuC3MN;I5CuMM,WATQ;IAUR,aARqB;;;;A4CtL3B;E5CEA,OOfkB;EqCgBhB;EAEA,kBrCD2B;;AF6LvB;EuCjMN;I5CKE,OOQsB;;;AFoLlB;EuCjMN;IAQI,SAPe;;;AAYjB;EAGE;EAOA;;AAGF;EACE;;;AAIJ;E5C0JI,WAJc;EAKd,aAJuB;EA5J3B;E4CSE;EAEA;;AvC4JI;EuClKN;I5CmKM,WAbY;IAcZ,aAbqB;;;AKWrB;EuClKN;I5C8JM,WATQ;IAUR,aARqB;;;;A4C9I3B;E5C5DA,aCFkB;EDGlB;EACA;EEaA;EAGE,2BChB6B;EDoB7B,uBCP0B;;AEsMtB;EuCzJN;I5CjDE,aCHsB;;;ACTxB;EAqCE,2BCLmC;EDQnC;EACQ;EACR;EACQ;;AAvCV;EIFA;EACA,OC4DwB;ED3DxB,kBCiDmB;EDhDnB,YACE;EAIF;EAIA;EACQ;;AJ8QR;EACE,OKvKgB;;AL0KlB;EACE,OK3KgB;;AL8KlB;EACE,OKjKsB;;ALoKxB;EACE,OK9JuB;;ALmKzB;EACE,OKjPsB;;;AqCGxB;EACE,crCcmB;EqCZnB,kBrCYmB;;AL2DrB;EAEE,OK7DmB;;ALgErB;EACE;;AAGF;EACE,OKrEmB;;AL0ErB;EACE,OK7FsB;;;;AsC1ExB;EpCuGM;EoCrGJ;EACA;EACA;EACA;;AxC4NI;EwCjON;IpC8GQ;;;AJmHF;EwCjON;IAQI;IACA;;;;AAIJ;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;E7CPA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;E6C/LzB;EACA;EACA;EACA;EACA;EACA;;AxCqMI;EwC9MN;AAAA;AAAA;I7CIE,aCHsB;;;AI6MlB;EwC9MN;AAAA;AAAA;I7C+MM,WAbY;IAcZ,aAbqB;;;AKWrB;EwC9MN;AAAA;AAAA;I7C0MM,WATQ;IA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R,aARqB;;;;AsDlK3B;EtDqKI,WAJc;EAKd,aAJuB;;AKWrB;EiD7KN;ItD8KM,WAbY;IAcZ,aAbqB;;;AKWrB;EiD7KN;ItDyKM,WATQ;IAUR,aARqB;;;;AsD9J3B;EtDiKI,WAJc;EAKd,aAJuB;;AKWrB;EiDzKN;ItD0KM,WAbY;IAcZ,aAbqB;;;AKWrB;EiDzKN;ItDqKM,WATQ;IAUR,aARqB;;;;;AuDxN3B;E9CyGM;EAAA;ET3FN,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;;AKWrB;EkDnON;I9CgHQ;;;AJmHF;EkDnON;IvDyBE,aCHsB;;;AI6MlB;EkDnON;IvDoOM,WAbY;IAcZ,aAbqB;;;AKWrB;EkDnON;IvD+NM,WATQ;IAUR,aARqB;;;;AuDlN3B;EvDqNI,WAJc;EAKd,aAJuB;EAtK3B;EAdA,OOfkB;EgDThB;;AlDuNI;EkD7NN;IvD8NM,WAbY;IAcZ,aAbqB;;;AKWrB;EkD7NN;IvDyNM,WATQ;IAUR,aARqB;;;AKWrB;EkD7NN;IvDiCE,OOQsB;;;;AgDhCxB;EACE;EACA;EACA;E9CuFI;;AJ0HA;EkDpNN;I9CiGQ;;;;A8C1FR;EACE;;AAEA;EvDWF,OOfkB;EgDMd;EACA;EACA;;AlDsME;EkD1MJ;IvDcA,OOQsB;;;;AgDdxB;EvDnBA,aCFkB;EDGlB;EACA;EEaA;EAGE,2BChB6B;EDoB7B,uBCP0B;EoDQ1B;EACA;;AlD6LI;EkDlMN;IvDRE,aCHsB;;;ACTxB;EAqCE,2BCLmC;EDQnC;EACQ;EACR;EACQ;;AAvCV;EIFA;EACA,OC4DwB;ED3DxB,kBCiDmB;EDhDnB,YACE;EAIF;EAIA;EACQ;;AJgDR;EACE,OKuDgB;;ALpDlB;EACE,OK0DwB;;ALvD1B;EACE,OK6DsB;;AL1DxB;EACE,OKgEuB;;AL3DzB;EACE,OKnBsB;;;AgDnCxB;E9CgEM;;AJ0HA;EkD1LN;I9CuEQ;;;;AJmHF;EkDnLF;IAEE;IACA;;EzC3CN;IACE;IACA;IACA;;EyC2CE;IACE;;EAGF;IACE;IAEA;IACA;IACA;IACA;IAEA;IACA;IACA;;EAEA;IACE;;EAIJ;IAGE;IAEA;IAGA;IACA;IACA;IACA;IACA;IAEA;IACA;IAEA,kBhDtDuB;;EgDwDvB;IACE;;EAIJ;IAGE;;ErD0HN;IF5LA,OOfkB;;;AF8MZ;EHHN;IFzLE,OOQsB;;;AFoLlB;EHIN;IAEI;;EAIJ;IFzMA,OOfkB;;;AF8MZ;EHUN;IFtME,OOQsB;;;AFoLlB;EkD3HA;IACE;IACA;IACA;IACA;IACA;IACA;;EAIJ;I9CTE;I8CWA;IACA;IACA;;EAEA;IACE;;EAIJ;IACE;;;;;;;AC1HN;ExDUA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EwDlNzB;E/CmGI;E+CjGJ;EACA;;AnD0NI;EmD/NN;IxDqBE,aCHsB;;;AI6MlB;EmD/NN;IxDgOM,WAbY;IAcZ,aAbqB;;;AKWrB;EmD/NN;IxD2NM,WATQ;IAUR,aARqB;;;AKWrB;EmD/NN;I/C4GQ;;;;A+C/FR;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAMF;EACE,YAjC6B;;;AAoC/B;EACE;EACA;ExDJF,OOfkB;;AF8MZ;EmD7LN;IxDCE,OOQsB;;;;AiDHxB;EACE;EACA;EACA;EACA;ExDZF,OOfkB;;AF8MZ;EmDvLN;IxDLE,OOQsB;;;;AiDKxB;EACE,OjDG0B;;;AiDG5B;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA,OjDf0B;;;;;;;;AkDxD5B;EzDcA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;ES/GrB;EgDtGJ;EACA;;ApD+NI;EoDnON;IzDyBE,aCHsB;;;AI6MlB;EoDnON;IzDoOM,WAbY;IAcZ,aAbqB;;;AKWrB;EoDnON;IzD+NM,WATQ;IAUR,aARqB;;;AKWrB;EoDnON;IhDgHQ;;;;AgDzGR;EzDqDA;EyDjDE;EAEA;EAEA;EACA;EAEA;EACA;EACA;EAQA;EACA;EAEA;EACA;EAEA;EACA;EAEA;EAIA;EACI;EACI;EAIR;;ApDoLI;EoD5NN;IAgBI;;;AA0BF;EA1CF;IA2CI;IACA;IACA;;;;AAIJ;EzDpBA,OOfkB;EkDqChB;EACA;;ApDwKI;EoD3KN;IzDjBE,OOQsB;;;;;;AOvCxB;EACE;EACA;EACA;;;;A4CXF;ENeA;EAcA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAKA;EAKA;EACI;EACI;;AAhCR;EACE;;AAGF;EACE;;;AMtBF;ENgEA;EAEA;EACA;EAGA;EAEA;EACA;EACA;EACQ;EAKR;EAKA;EACI;EACI;;AAER;EAEE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAGA;EACI;EACI;;;;;AO9GV;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AtDqNI;EsDjNJ;IACE;;;;ACiBF;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDhDN;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;;ACrEN;EACE;;;AAGF;EACE;;;AAGF;EACE;;;;ACHA;E9DoNE,WAJc;EAKd,aAJuB;;AKWrB;EyD5NJ;I9D6NI,WAbY;IAcZ,aAbqB;;;AKWrB;EyD5NJ;I9DwNI,WATQ;IAUR,aARqB;;;;A8DjNzB;E9DoNE,WAJc;EAKd,aAJuB;;AKWrB;EyD5NJ;I9D6NI,WAbY;IAcZ,aAbqB;;;AKWrB;EyD5NJ;I9DwNI,WATQ;IAUR,aARqB;;;;A8DjNzB;E9DoNE,WAJc;EAKd,aAJuB;;AKWrB;EyD5NJ;I9D6NI,WAbY;IAcZ,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","file":"base.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../../node_modules/govuk-frontend/dist/govuk/core/_govuk-frontend-properties.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_links.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_typography.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_typography-font.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_links.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_links.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_font-faces.scss","../../../node_modules/govuk-frontend/dist/govuk/vendor/_sass-mq.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_focused.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_colours-applied.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_lists.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_spacing.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_typography.scss","../../../node_modules/govuk-frontend/dist/govuk/core/_section-break.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_button-group.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_form-group.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_clearfix.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_grid.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_grid.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_main-wrapper.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_template.scss","../../../node_modules/govuk-frontend/dist/govuk/objects/_width-container.scss","../../../node_modules/govuk-frontend/dist/govuk/settings/_measurements.scss","../../../node_modules/govuk-frontend/dist/govuk/components/accordion/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/back-link/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/breadcrumbs/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/button/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/error-message/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/hint/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/label/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/textarea/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/character-count/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/fieldset/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/checkboxes/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/cookie-banner/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/input/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/date-input/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/details/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_shape-arrow.scss","../../../node_modules/govuk-frontend/dist/govuk/components/error-summary/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/exit-this-page/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/file-upload/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/footer/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_device-pixels.scss","../../../node_modules/govuk-frontend/dist/govuk/components/header/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/inset-text/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/notification-banner/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/pagination/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/panel/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/tag/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/phase-banner/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/radios/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/select/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/skip-link/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/helpers/_visually-hidden.scss","../../../node_modules/govuk-frontend/dist/govuk/components/summary-list/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/table/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/tabs/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/task-list/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/components/warning-text/_index.scss","../../../node_modules/govuk-frontend/dist/govuk/utilities/_visually-hidden.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_display.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_spacing.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_text-align.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_typography.scss","../../../node_modules/govuk-frontend/dist/govuk/overrides/_width.scss","../../../node_modules/@ministryofjustice/frontend/moj/settings/_assets.scss","../../../node_modules/@ministryofjustice/frontend/moj/settings/_measurements.scss","../../../node_modules/@ministryofjustice/frontend/moj/settings/_colours.scss","../../../node_modules/@ministryofjustice/frontend/moj/objects/_filter-layout.scss","../../../node_modules/@ministryofjustice/frontend/moj/objects/_scrollable-pane.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/action-bar/_action-bar.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/add-another/_add-another.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/badge/_badge.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/banner/_banner.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/button-menu/_button-menu.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/cookie-banner/_cookie-banner.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/currency-input/_currency-input.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/filter/_filter.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/header/_header.scss","../../../node_modules/@ministryofjustice/frontend/moj/objects/_width-container.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/identity-bar/_identity-bar.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/messages/_messages.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/multi-file-upload/_multi-file-upload.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/multi-select/_multi-select.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/notification-badge/_notification-badge.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/organisation-switcher/_organisation-switcher.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/page-header-actions/_page-header-actions.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/pagination/_pagination.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/password-reveal/_password-reveal.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/primary-navigation/_primary-navigation.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/progress-bar/_progress-bar.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/rich-text-editor/_rich-text-editor.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/search-toggle/search-toggle.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/search/_search.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/side-navigation/_side-navigation.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/sortable-table/_sortable-table.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/sub-navigation/_sub-navigation.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/tag/_tag.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/task-list/_task-list.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/timeline/_timeline.scss","../../../node_modules/@ministryofjustice/frontend/moj/components/ticket-panel/_ticket-panel.scss","../../../node_modules/@ministryofjustice/frontend/moj/utilities/_hidden.scss","../../../node_modules/@ministryofjustice/frontend/moj/helpers/_hidden.scss","../../../node_modules/@ministryofjustice/frontend/moj/utilities/_width-container.scss","../../../scss/base.scss"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;EAGE;EAIE;EAAA;EAAA;;;;ACNF;ECcA,aCFkB;EDGlB;EACA;EEaA;EAGE,2BChB6B;EDoB7B,uBCP0B;;ACdxB;AACA;EACE;EACA;EACA;EACA,KACE;EAEF;;AAGF;EACE;EACA;EACA;EACA,KACE;EAEF;;ACkMA;ENnON;ICyBE,aCHsB;;;ACTxB;EAqCE,2BCLmC;EDQnC;EACQ;EACR;EACQ;;AAvCV;EIFA;EACA,OC4DwB;ED3DxB,kBCiDmB;EDhDnB,YACE;EAIF;EAIA;EACQ;;AJgDR;EACE,OKuDgB;;ALpDlB;EACE,OK0DwB;;ALvD1B;EACE,OK6DsB;;AL1DxB;EACE,OKgEuB;;AL3DzB;EACE,OKnBsB;;AFuJlB;EH+HF;IACE;IACA;IAKA;;;;AA3KN;EAEE,OKxI0B;;AL2I5B;EAEE,OKhLgB;;ALqLlB;EACE,OK/HsB;;;ALoJxB;EF5LA,OOfkB;;AF8MZ;EHHN;IFzLE,OOQsB;;;ALwLxB;EAEI;;AAIJ;EFzMA,OOfkB;;AF8MZ;EHUN;IFtME,OOQsB;;;;ALqNxB;EAEE;;AAKF;EAEE;;AAGF;EACE,OKrMsB;;;ALoQxB;EACE;;;AAvCF;EACE,OKvKgB;;AL0KlB;EACE,OK3KgB;;AL8KlB;EACE,OKjKsB;;ALoKxB;EACE,OK9JuB;;ALmKzB;EACE,OKjPsB;;;ARzCxB;EGqVA;EAGA;EAGA;;AAEA;EIvVA;EACA,YACE;;;;AE3CF;ERcA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EApL3B,OOfkB;EClBhB;ECsGI;EDpGJ;EACA;;AH6NI;EGnON;IRyBE,aCHsB;;;AI6MlB;EGnON;IRoOM,WAbY;IAcZ,aAbqB;;;AKWrB;EGnON;IR+NM,WATQ;IAUR,aARqB;;;AKWrB;EGnON;IRuCE,OOQsB;;;AFoLlB;EGnON;ICgHQ;;;ADvGN;EACE;;;AAIJ;EAIE;;;AAOF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;;AH8LI;EGhMN;AAAA;IAKI;;;;AAIJ;EACE;;AHsLI;EGvLN;IAII;;;;;AE9CJ;EVkCA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUlNzB;EAEA;EDiGI;;AJ0HA;EKjON;IVqCE,OOQsB;;;AFoLlB;EKjON;IVuBE,aCHsB;;;AI6MlB;EKjON;IVkOM,WAbY;IAcZ,aAbqB;;;AKWrB;EKjON;IV6NM,WATQ;IAUR,aARqB;;;AKWrB;EKjON;ID8GQ;;;;AChGR;EVoBA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUpMzB;EAEA;EDmFI;;AJ0HA;EKnNN;IVuBE,OOQsB;;;AFoLlB;EKnNN;IVSE,aCHsB;;;AI6MlB;EKnNN;IVoNM,WAbY;IAcZ,aAbqB;;;AKWrB;EKnNN;IV+MM,WATQ;IAUR,aARqB;;;AKWrB;EKnNN;IDgGQ;;;;AClFR;EVMA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUtLzB;EAEA;EDqEI;;AJ0HA;EKrMN;IVSE,OOQsB;;;AFoLlB;EKrMN;IVLE,aCHsB;;;AI6MlB;EKrMN;IVsMM,WAbY;IAcZ,aAbqB;;;AKWrB;EKrMN;IViMM,WATQ;IAUR,aARqB;;;AKWrB;EKrMN;IDkFQ;;;;ACpER;EVRA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EUxKzB;EAEA;EDuDI;;AJ0HA;EKvLN;IVLE,OOQsB;;;AFoLlB;EKvLN;IVnBE,aCHsB;;;AI6MlB;EKvLN;IVwLM,WAbY;IAcZ,aAbqB;;;AKWrB;EKvLN;IVmLM,WATQ;IAUR,aARqB;;;AKWrB;EKvLN;IDoEQ;;;;ACpDR;EV9CA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUzJzB;EAEA;EAEA,OHX0B;;AF2KtB;EKvKN;IVnCE,aCHsB;;;AI6MlB;EKvKN;IVwKM,WAbY;IAcZ,aAbqB;;;AKWrB;EKvKN;IVmKM,WATQ;IAUR,aARqB;;;;AUlJ3B;EVxDA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EU/IzB;EAEA;EACA,OHpB0B;;AF2KtB;EK7JN;IV7CE,aCHsB;;;AI6MlB;EK7JN;IV8JM,WAbY;IAcZ,aAbqB;;;AKWrB;EK7JN;IVyJM,WATQ;IAUR,aARqB;;;AKWrB;EK7JN;IASI;;;;AAIJ;EVrEA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUlIzB;EAEA,OHhC0B;;AF2KtB;EKhJN;IV1DE,aCHsB;;;AI6MlB;EKhJN;IViJM,WAbY;IAcZ,aAbqB;;;AKWrB;EKhJN;IV4IM,WATQ;IAUR,aARqB;;;;AU3H3B;EVzDA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUvHzB;EDQI;;AJ0HA;EKtIN;IVtDE,OOQsB;;;AFoLlB;EKtIN;IVpEE,aCHsB;;;AI6MlB;EKtIN;IVuIM,WAbY;IAcZ,aAbqB;;;AKWrB;EKtIN;IVkIM,WATQ;IAUR,aARqB;;;AKWrB;EKtIN;IDmBQ;;;;ACPR;EVrEA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EU3GzB;EDJI;;AJ0HA;EK1HN;IVlEE,OOQsB;;;AFoLlB;EK1HN;IVhFE,aCHsB;;;AI6MlB;EK1HN;IV2HM,WAbY;IAcZ,aAbqB;;;AKWrB;EK1HN;IVsHM,WATQ;IAUR,aARqB;;;AKWrB;EK1HN;IDOQ;;;;ACKR;EVjFA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EU/FzB;EDhBI;;AJ0HA;EK9GN;IV9EE,OOQsB;;;AFoLlB;EK9GN;IV5FE,aCHsB;;;AI6MlB;EK9GN;IV+GM,WAbY;IAcZ,aAbqB;;;AKWrB;EK9GN;IV0GM,WATQ;IAUR,aARqB;;;AKWrB;EK9GN;IDLQ;;;;ACkBR;EV9FA,OOfkB;EPPlB,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EUlFzB;ED7BI;;AJ0HA;EKjGN;IV3FE,OOQsB;;;AFoLlB;EKjGN;IVzGE,aCHsB;;;AI6MlB;EKjGN;IVkGM,WAbY;IAcZ,aAbqB;;;AKWrB;EKjGN;IV6FM,WATQ;IAUR,aARqB;;;AKWrB;EKjGN;IDlBQ;;;;AC+CR;EACE;;ALmEI;EKpEN;IAII;;;;AAIJ;AAAA;AAAA;ED9DM;;AJ0HA;EK5DN;AAAA;AAAA;IDvDQ;;;;AC6DR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;ALgDI;EKtDN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;IASI;;;;;ACtLJ;EACE;EACA;;;AASF;EF8FM;EAAA;;AJ0HA;EMxNN;IFqGQ;;;AJmHF;EMxNN;IFqGQ;;;;AE5FR;EFqFM;EAAA;;AJ0HA;EM/MN;IF4FQ;;;AJmHF;EM/MN;IF4FQ;;;;AEnFR;EF4EM;EAAA;;AJ0HA;EMtMN;IFmFQ;;;AJmHF;EMtMN;IFmFQ;;;;AExER;EACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC/BF;EH+FM;EG3EJ;EACA;EACA;;APmMI;EOzNN;IHsGQ;;;AGzEN;EZzBF,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EY/KvB;EAGA;EACA,YA3Ba;EA4Bb;EACA;;APoLE;EO5LJ;IZdA,aCHsB;;;AI6MlB;EO5LJ;IZ6LI,WAbY;IAcZ,aAbqB;;;AKWrB;EO5LJ;IZwLI,WATQ;IAUR,aARqB;;;AYpKzB;EACE;;AP8KE;EOzNN;IAkDI;IAEA;IACA;IACA;;EAEA;AAAA;IAEE,cAzDa;;EA4Df;IACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtEN;EJuGM;;AKjGN;EACE;EACA;EACA;;ATwNI;EQjON;IJ8GQ;;;AI1GN;EACE;;;AAIJ;EACE;EACA;;AAEA;EAEE;EACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEhBJ;EAEE;EACA;;ADGF;EACE;EACA;EACA;;;ACFA;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1B7C;EAIE;EACA;EACA;;AZsMI;EY5MN;IAYI;IACA;;;;AAWJ;AAAA;ER0DM;;AJ0HA;EYpLN;AAAA;IRiEQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AS7GR;EAGE,kBXyB6B;EWrB7B;EACG;EACK;;AAcR;EAvBF;IAwBI;;EAEA;IACE;;;AbqMA;EahON;IAkCI;;;;AAKJ;EAGE;EAEA,kBXT2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AYgC7B;EAlDA,WCRiB;EDWjB,cC2BkB;ED1BlB,aC0BkB;;ADvBlB;EA2CA;IArCE;IACA;;;AdiMI;Ec7JN;IA/BE,cCIW;IDHX,aCGW;;EDAX;IA2BF;MArBI;MACA;;;;AdiLE;Ec7JN;IAbE;IACA;;EAIA;IAQF;MAPI;MACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AE3DJ;EZoGM;;AJ0HA;EgB9NN;IZ2GQ;;;;AYvGR;EACE;;;AAGF;EAEE;EACA;EAEA;EACA;;;AAGF;ErBRA,aCFkB;EDGlB;EACA;EA4CA;EA+JI,WAJc;EAKd,aAJuB;EApL3B,OOfkB;EcKhB;EACA;EACA;;AhBuMI;EgB7MN;IrBGE,aCHs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;;;AKWrB;EuCnON;InCgHQ;;;AmCxGN;EACE;;;AAIJ;EACE;EAGA;;AvCkNI;EuCtNN;IAOI;;;;AAIJ;E5CmMI,WAJc;EAKd,aAJuB;EA5J3B;E4C/BE;EACA;EACA;;AvCoMI;EuC3MN;I5C4MM,WAbY;IAcZ,aAbqB;;;AKWrB;EuC3MN;I5CuMM,WATQ;IAUR,aARqB;;;;A4CtL3B;E5CEA,OOfkB;EqCgBhB;EAEA,kBrCD2B;;AF6LvB;EuCjMN;I5CKE,OOQsB;;;AFoLlB;EuCjMN;IAQI,SAPe;;;AAYjB;EAGE;EAOA;;AAGF;EACE;;;AAIJ;E5C0JI,WAJc;EAKd,aAJuB;EA5J3B;E4CSE;EAEA;;AvC4JI;EuClKN;I5CmKM,WAbY;IAcZ,aAbqB;;;AKWrB;EuClKN;I5C8JM,WATQ;IAUR,aARqB;;;;A4C9I3B;E5C5DA,aCFkB;EDGlB;EACA;EEaA;EAGE,2BChB6B;EDoB7B,uBCP0B;;AEsMtB;EuCzJN;I5CjDE,aCHsB;;;ACTxB;EAqCE,2BCLmC;EDQnC;EACQ;EACR;EACQ;;AAvCV;EIFA;EACA,OC4DwB;ED3DxB,kBCiDmB;EDhDnB,YACE;EAIF;EAIA;EACQ;;AJ8QR;EACE,OKvKgB;;AL0KlB;EACE,OK3KgB;;AL8KlB;EACE,OKjKsB;;ALoKxB;EACE,OK9JuB;;ALmKzB;EACE,OKjPsB;;;AqCGxB;EACE,crCcmB;EqCZnB,kBrCYmB;;AL2DrB;EAEE,OK7DmB;;ALgErB;EACE;;AAGF;EACE,OKrEmB;;AL0ErB;EACE,OK7FsB;;;;AsC1ExB;EpCuGM;EoCrGJ;EACA;EACA;EACA;;AxC4NI;EwCjON;IpC8GQ;;;AJmHF;EwCjON;IAQI;IACA;;;;AAIJ;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;E7CPA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;E6C/LzB;EACA;EACA;EACA;EACA;EACA;;AxCqMI;EwC9MN;AAAA;AAAA;I7CIE,aCHsB;;;AI6MlB;EwC9MN;AAAA;AAAA;I7C+MM,WAbY;IAcZ,aAbqB;;;AKWrB;EwC9MN;AAAA;AAAA;I7C0MM,WATQ;IA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R,aARqB;;;;AsDlK3B;EtDqKI,WAJc;EAKd,aAJuB;;AKWrB;EiD7KN;ItD8KM,WAbY;IAcZ,aAbqB;;;AKWrB;EiD7KN;ItDyKM,WATQ;IAUR,aARqB;;;;AsD9J3B;EtDiKI,WAJc;EAKd,aAJuB;;AKWrB;EiDzKN;ItD0KM,WAbY;IAcZ,aAbqB;;;AKWrB;EiDzKN;ItDqKM,WATQ;IAUR,aARqB;;;;;AuDxN3B;E9CyGM;EAAA;ET3FN,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;;AKWrB;EkDnON;I9CgHQ;;;AJmHF;EkDnON;IvDyBE,aCHsB;;;AI6MlB;EkDnON;IvDoOM,WAbY;IAcZ,aAbqB;;;AKWrB;EkDnON;IvD+NM,WATQ;IAUR,aARqB;;;;AuDlN3B;EvDqNI,WAJc;EAKd,aAJuB;EAtK3B;EAdA,OOfkB;EgDThB;;AlDuNI;EkD7NN;IvD8NM,WAbY;IAcZ,aAbqB;;;AKWrB;EkD7NN;IvDyNM,WATQ;IAUR,aARqB;;;AKWrB;EkD7NN;IvDiCE,OOQsB;;;;AgDhCxB;EACE;EACA;EACA;E9CuFI;;AJ0HA;EkDpNN;I9CiGQ;;;;A8C1FR;EACE;;AAEA;EvDWF,OOfkB;EgDMd;EACA;EACA;;AlDsME;EkD1MJ;IvDcA,OOQsB;;;;AgDdxB;EvDnBA,aCFkB;EDGlB;EACA;EEaA;EAGE,2BChB6B;EDoB7B,uBCP0B;EoDQ1B;EACA;;AlD6LI;EkDlMN;IvDRE,aCHsB;;;ACTxB;EAqCE,2BCLmC;EDQnC;EACQ;EACR;EACQ;;AAvCV;EIFA;EACA,OC4DwB;ED3DxB,kBCiDmB;EDhDnB,YACE;EAIF;EAIA;EACQ;;AJgDR;EACE,OKuDgB;;ALpDlB;EACE,OK0DwB;;ALvD1B;EACE,OK6DsB;;AL1DxB;EACE,OKgEuB;;AL3DzB;EACE,OKnBsB;;;AgDnCxB;E9CgEM;;AJ0HA;EkD1LN;I9CuEQ;;;;AJmHF;EkDnLF;IAEE;IACA;;EzC3CN;IACE;IACA;IACA;;EyC2CE;IACE;;EAGF;IACE;IAEA;IACA;IACA;IACA;IAEA;IACA;IACA;;EAEA;IACE;;EAIJ;IAGE;IAEA;IAGA;IACA;IACA;IACA;IACA;IAEA;IACA;IAEA,kBhDtDuB;;EgDwDvB;IACE;;EAIJ;IAGE;;ErD0HN;IF5LA,OOfkB;;;AF8MZ;EHHN;IFzLE,OOQsB;;;AFoLlB;EHIN;IAEI;;EAIJ;IFzMA,OOfkB;;;AF8MZ;EHUN;IFtME,OOQsB;;;AFoLlB;EkD3HA;IACE;IACA;IACA;IACA;IACA;IACA;;EAIJ;I9CTE;I8CWA;IACA;IACA;;EAEA;IACE;;EAIJ;IACE;;;;;;;AC1HN;ExDUA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;EwDlNzB;E/CmGI;E+CjGJ;EACA;;AnD0NI;EmD/NN;IxDqBE,aCHsB;;;AI6MlB;EmD/NN;IxDgOM,WAbY;IAcZ,aAbqB;;;AKWrB;EmD/NN;IxD2NM,WATQ;IAUR,aARqB;;;AKWrB;EmD/NN;I/C4GQ;;;;A+C/FR;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAMF;EACE,YAjC6B;;;AAoC/B;EACE;EACA;ExDJF,OOfkB;;AF8MZ;EmD7LN;IxDCE,OOQsB;;;;AiDHxB;EACE;EACA;EACA;EACA;ExDZF,OOfkB;;AF8MZ;EmDvLN;IxDLE,OOQsB;;;;AiDKxB;EACE,OjDG0B;;;AiDG5B;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA,OjDf0B;;;;;;;;AkDxD5B;EzDcA,aCFkB;EDGlB;EACA;EAkCA;EAyKI,WAJc;EAKd,aAJuB;ES/GrB;EgDtGJ;EACA;;ApD+NI;EoDnON;IzDyBE,aCHsB;;;AI6MlB;EoDnON;IzDoOM,WAbY;IAcZ,aAbqB;;;AKWrB;EoDnON;IzD+NM,WATQ;IAUR,aARqB;;;AKWrB;EoDnON;IhDgHQ;;;;AgDzGR;EzDqDA;EyDjDE;EAEA;EAEA;EACA;EAEA;EACA;EACA;EAQA;EACA;EAEA;EACA;EAEA;EACA;EAEA;EAIA;EACI;EACI;EAIR;;ApDoLI;EoD5NN;IAgBI;;;AA0BF;EA1CF;IA2CI;IACA;IACA;;;;AAIJ;EzDpBA,OOfkB;EkDqChB;EACA;;ApDwKI;EoD3KN;IzDjBE,OOQsB;;;;;;AOvCxB;EACE;EACA;EACA;;;;A4CXF;ENeA;EAcA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAKA;EAKA;EACI;EACI;;AAhCR;EACE;;AAGF;EACE;;;AMtBF;ENgEA;EAEA;EACA;EAGA;EAEA;EACA;EACA;EACQ;EAKR;EAKA;EACI;EACI;;AAER;EAEE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAGA;EACI;EACI;;;;;AO9GV;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AtDqNI;EsDjNJ;IACE;;;;ACiBF;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;;AmD7DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmD/DF;EnD+DE;;;AmDrEJ;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmD5EN;EnDmEI;;AJ4HA;EuD/LJ;InD0EM;;;;AmDpEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDtEJ;EnD+DE;;AJ0HA;EuDzLF;InDsEI;;;;AmDhDN;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;AANJ;EACE;;;AAIA;EACE;;;AADF;EACE;;;AADF;EACE;;;AADF;EACE;;;;ACrEN;EACE;;;AAGF;EACE;;;AAGF;EACE;;;;ACHA;E9DoNE,WAJc;EAKd,aAJuB;;AKWrB;EyD5NJ;I9D6NI,WAbY;IAcZ,aAbqB;;;AKWrB;EyD5NJ;I9DwNI,WATQ;IAUR,aARqB;;;;A8DjNzB;E9DoNE,WAJc;EAKd,aAJuB;;AKWrB;EyD5NJ;I9D6NI,WAbY;IAcZ,aAbqB;;;AKWrB;EyD5NJ;I9DwNI,WATQ;IAUR,aARqB;;;;A8DjNzB;E9DoNE,WAJc;EAKd,aAJuB;;AKWrB;EyD5NJ;I9D6NI,WAbY;IAcZ,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","file":"base.css"} \ No newline at end of file diff --git a/static/assets/js/enhanced-search.js b/static/assets/js/enhanced-search.js new file mode 100644 index 00000000..cc1dac4d --- /dev/null +++ b/static/assets/js/enhanced-search.js @@ -0,0 +1,138 @@ +/** + * Enhance the domain filter to include a subdomain input in addition + * to the domain filter. When a domain is selected, the widget should + * dynamically populate the subdomain options, and when a domain is + * cleared, the subdomain filter should be disabled. + * + * Note: This widget does not automatically refresh the results - the user + * has to hit "Apply filters" first. + */ + +const ALL_DOMAINS_VALUE = "*"; + +export const initDomainFilter = () => { + const subdomainSelect = document.querySelector("#subdomains-filter"); + const topLevelDomainSelect = document.querySelector("#domains-filter"); + const subdomainGroup = document.querySelector(".js-required"); + + if (subdomainSelect === null || topLevelDomainSelect === null) { + return; + } + + subdomainGroup.style.display = "block"; + + new DomainFilter(topLevelDomainSelect, subdomainSelect); +}; + +class DomainFilter { + constructor(topLevelDomainSelect, subdomainSelect) { + this.topLevelDomainSelect = topLevelDomainSelect; + this.subdomainSelect = subdomainSelect; + this.options = this.#extractSubdomainOptions(); + this.#onClearTopLevelDomain(); + + topLevelDomainSelect.addEventListener("change", () => + this.#onChangeDomain() + ); + subdomainSelect.addEventListener("change", () => this.#notify()); + } + + get state() { + const topLevelDomainOption = this.topLevelDomainSelect.selectedOptions[0]; + const subdomainOption = this.subdomainSelect.selectedOptions[0]; + + if (this.isWildcardTopLevelDomain()) { + return { + topLevelDomainValue: null, + subdomainValue: null, + label: null, + }; + } else if (this.isWildcardSubdomain()) { + return { + topLevelDomainValue: this.topLevelDomainSelect.value, + subdomainValue: null, + label: topLevelDomainOption.label, + }; + } else { + return { + topLevelDomainValue: this.topLevelDomainSelect.value, + subdomainValue: subdomainOption.value, + label: `${topLevelDomainOption.label} - ${subdomainOption.label}`, + }; + } + } + + #onChangeDomain() { + const selectedDomain = this.topLevelDomainSelect.value; + if (this.isWildcardTopLevelDomain()) { + this.#onClearTopLevelDomain(); + } else { + this.#onSelectTopLevelDomain(selectedDomain); + } + + this.#notify(); + } + + #onSelectTopLevelDomain(selectedDomain) { + this.subdomainSelect.disabled = false; + this.#setSubdomainOptions(this.options[selectedDomain]); + } + + #onClearTopLevelDomain() { + this.#setSubdomainOptions([]); + this.subdomainSelect.disabled = true; + } + + isWildcardSubdomain() { + return this.subdomainSelect.value === ALL_DOMAINS_VALUE; + } + + isWildcardTopLevelDomain() { + return this.topLevelDomainSelect.value === ALL_DOMAINS_VALUE; + } + + #setSubdomainOptions(newOptionElements) { + const existingOptionElements = + this.subdomainSelect.querySelectorAll("option"); + + existingOptionElements.forEach((option) => { + if (option.value != ALL_DOMAINS_VALUE) { + option.parentNode.removeChild(option); + option.selected = false; + } + }); + + if (newOptionElements === undefined) { + return; + } + + newOptionElements.forEach((option) => { + this.subdomainSelect.appendChild(option); + }); + } + + #extractSubdomainOptions() { + var options = {}; + var optionElements = this.subdomainSelect.querySelectorAll("option"); + + optionElements.forEach((option) => { + var parent = option.getAttribute("data-parent"); + options[parent] = options[parent] || []; + options[parent].push(option); + }); + + return options; + } + + /** + * Emit a custom event whenever a new selection is made, so + * that other parts of the UI can respond to this in real time. + */ + #notify() { + const event = new CustomEvent("domain-filter-updates", { + detail: this.state, + }); + + this.topLevelDomainSelect.parentElement.dispatchEvent(event); + } +} diff --git a/templates/base/base.html b/templates/base/base.html index dee6d7ed..4441cbd2 100644 --- a/templates/base/base.html +++ b/templates/base/base.html @@ -41,9 +41,11 @@ crossorigin="anonymous" > +{% block scripts %} +{% endblock scripts %} diff --git a/templates/search.html b/templates/search.html index 03436bea..358209be 100644 --- a/templates/search.html +++ b/templates/search.html @@ -33,3 +33,9 @@

{{tot {% endblock content %} +{% block scripts %} + +{% endblock scripts %} \ No newline at end of file diff --git a/tests/javascript/jest-setup.js b/tests/javascript/jest-setup.js new file mode 100644 index 00000000..d0de870d --- /dev/null +++ b/tests/javascript/jest-setup.js @@ -0,0 +1 @@ +import "@testing-library/jest-dom"; diff --git a/tests/javascript/test_enhanced_search.js b/tests/javascript/test_enhanced_search.js new file mode 100644 index 00000000..4920b383 --- /dev/null +++ b/tests/javascript/test_enhanced_search.js @@ -0,0 +1,166 @@ +import { initDomainFilter } from "enhanced-search"; +import { expect, test } from "@jest/globals"; + +const widget_html = ` +
+ Domain +
+ + +
+
+ + +
+
+`; + +let subdomainFilter; +let domainFilter; +const eventSpy = jest.fn(); + +describe("initialisation", () => { + beforeEach(() => { + document.body.innerHTML = widget_html; + subdomainFilter = document.querySelector("#subdomains-filter"); + initDomainFilter(); + }); + + test("subdomain select is disabled", () => { + expect(subdomainFilter).toBeDisabled(); + }); + + test("the only option is 'all subdomains'", () => { + expect(subdomainFilter).toHaveLength(1); + }); +}); + +describe("after selecting a domain", () => { + beforeEach(() => { + document.body.innerHTML = widget_html; + + subdomainFilter = document.querySelector("#subdomains-filter"); + domainFilter = document.querySelector("#domains-filter"); + + initDomainFilter(); + + // Listen to outgoing events + domainFilter.parentElement.addEventListener( + "domain-filter-updates", + eventSpy + ); + + // Emulate selecting a domain + domainFilter.value = "a"; + domainFilter.dispatchEvent(new Event("change")); + }); + + test("only the selected domain's options are available", () => { + const options = subdomainFilter.querySelectorAll("option"); + + const values = Array.from(options).map((el) => el.value); + + expect(values).toEqual(["*", "a1", "a2"]); + }); + + test("fires an event with the selected domain and null subdomain", () => { + expect(eventSpy.mock.calls[0][0].detail).toEqual({ + topLevelDomainValue: "a", + subdomainValue: null, + label: "Domain A", + }); + }); + + describe("after selecting a subdomain", () => { + beforeEach(() => { + // Emulate selecting a subdomain + subdomainFilter.value = "a1"; + subdomainFilter.dispatchEvent(new Event("change")); + }); + + test("fires an event with the selected domain/subdomain pair", () => { + expect(eventSpy.mock.calls[1][0].detail).toEqual({ + topLevelDomainValue: "a", + subdomainValue: "a1", + label: "Domain A - Subdomain of A 1", + }); + }); + + describe("after changing to another top level domain", () => { + beforeEach(() => { + domainFilter.value = "b"; + domainFilter.dispatchEvent(new Event("change")); + }); + + test("only the new domain's options are available", () => { + const options = subdomainFilter.querySelectorAll("option"); + + const values = Array.from(options).map((el) => el.value); + + expect(values).toEqual(["*", "b1", "b2"]); + }); + + test("selects all subdomains", () => { + expect(subdomainFilter.value).toEqual("*"); + }); + + test("fires an event with the selected domain and null subdomain", () => { + expect(eventSpy.mock.calls[2][0].detail).toEqual({ + topLevelDomainValue: "b", + subdomainValue: null, + label: "Domain B", + }); + }); + + describe("after changing back to the original top level domain", () => { + beforeEach(() => { + domainFilter.value = "a"; + domainFilter.dispatchEvent(new Event("change")); + }); + + test("selects all subdomains", () => { + expect(subdomainFilter.value).toEqual("*"); + }); + }); + }); + + describe("after clearing the top level domain", () => { + beforeEach(() => { + domainFilter.value = "*"; + domainFilter.dispatchEvent(new Event("change")); + }); + + test("subdomain select is disabled", () => { + expect(subdomainFilter).toBeDisabled(); + }); + + test("the only option is 'all subdomains'", () => { + expect(subdomainFilter.options).toHaveLength(1); + }); + + test("fires an event with null domain/subdomain", () => { + expect(eventSpy.mock.calls[2][0].detail).toEqual({ + topLevelDomainValue: null, + subdomainValue: null, + label: null, + }); + }); + }); + }); +}); + +// TODO: clear selected subdomain when choosing parent domain From 54cb4bd62786a45c17f68f0cd945d433dfa001bc Mon Sep 17 00:00:00 2001 From: Mat Moore Date: Thu, 22 Feb 2024 11:17:20 +0000 Subject: [PATCH 44/60] Revert template - will add backend later --- templates/partial/filter.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/templates/partial/filter.html b/templates/partial/filter.html index e7af7286..a4c1931a 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -18,6 +18,7 @@

Filter

Domain +<<<<<<< HEAD {{form.domain}}
@@ -43,6 +44,14 @@

Filter

{{ access_option.tag}} +======= +
+ {% for domain_option in form.domains %} +
+ {{ domain_option.tag}} + +
+>>>>>>> 730c59e (Revert template - will add backend later) {% endfor %}
From 2b1fd7dabd89e115e629fd486b661f060da60bba Mon Sep 17 00:00:00 2001 From: Mat Moore Date: Mon, 26 Feb 2024 09:44:40 +0000 Subject: [PATCH 45/60] Add test --- tests/javascript/test_enhanced_search.js | 44 ++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/javascript/test_enhanced_search.js b/tests/javascript/test_enhanced_search.js index 4920b383..83d7ae8c 100644 --- a/tests/javascript/test_enhanced_search.js +++ b/tests/javascript/test_enhanced_search.js @@ -12,6 +12,7 @@ const widget_html = ` +
@@ -49,6 +50,47 @@ describe("initialisation", () => { }); }); +describe("after selecting a domain with no subdomains", () => { + beforeEach(() => { + document.body.innerHTML = widget_html; + + subdomainFilter = document.querySelector("#subdomains-filter"); + domainFilter = document.querySelector("#domains-filter"); + + initDomainFilter(); + + // Listen to outgoing events + domainFilter.parentElement.addEventListener( + "domain-filter-updates", + eventSpy + ); + + // Emulate selecting a domain + domainFilter.value = "c"; + domainFilter.dispatchEvent(new Event("change")); + }); + + test("selects all subdomains", () => { + expect(subdomainFilter.value).toEqual("*"); + }); + + test("only the all subdomains option is available", () => { + const options = subdomainFilter.querySelectorAll("option"); + + const values = Array.from(options).map((el) => el.value); + + expect(values).toEqual(["*"]); + }); + + test("fires an event with the selected domain/subdomain pair", () => { + expect(eventSpy.mock.calls[0][0].detail).toEqual({ + topLevelDomainValue: "c", + subdomainValue: null, + label: "Domain C", + }); + }); +}); + describe("after selecting a domain", () => { beforeEach(() => { document.body.innerHTML = widget_html; @@ -162,5 +204,3 @@ describe("after selecting a domain", () => { }); }); }); - -// TODO: clear selected subdomain when choosing parent domain From 369f4534fd98ab25aa267192b0034bd79acf253d Mon Sep 17 00:00:00 2001 From: Mat Moore Date: Mon, 26 Feb 2024 10:14:55 +0000 Subject: [PATCH 46/60] Install a compatable version of chrome/chromedriver The chromedriver library updates more frequently than the chrome distributed in ubuntu-latest, but these need to be the same version, otherwise axe-core breaks. As a workaround, try to install a version that matches whatever chrome is on the path. See also https://github.com/dequelabs/axe-core-npm/issues/401#issuecomment-1917605607 --- .github/workflows/test.yml | 10 +++++++++- tests/conftest.py | 14 +++++++++----- tests/selenium/helpers.py | 15 +++++++++++++-- tests/selenium/test_search_scenarios.py | 17 ++++++++++++++--- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f3441ea..a7c75df7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,10 +40,18 @@ jobs: id: fast-tests run: poetry run pytest --cov -m 'not slow' + - name: Get Chromium version 🌐 + run: | + CHROMIUM_VERSION=$(google-chrome --product-version) + echo "Chromium version: $CHROMIUM_VERSION" + echo "CHROMIUM_VERSION=$CHROMIUM_VERSION" >> $GITHUB_ENV + - name: Install chromedriver 🚗 + run: | + npm install -g chromedriver@${CHROMIUM_VERSION%.*.*} - name: run selenium tests id: slow-tests if: steps.fast-tests.outcome == 'success' - run: poetry run pytest -m 'slow' + run: poetry run pytest -m 'slow' --chromedriver-path=$(npm root -g)/chromedriver/bin/chromedriver test_javascript: runs-on: ubuntu-latest diff --git a/tests/conftest.py b/tests/conftest.py index 6b16df91..14c6ce11 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,6 +25,15 @@ fake = Faker() +def pytest_addoption(parser): + parser.addoption("--chromedriver-path", action="store") + + +@pytest.fixture +def chromedriver_path(request): + return request.config.getoption("--chromedriver-path") + + def generate_page(page_size=20, result_type: ResultType = None): """ Generate a fake search page @@ -35,11 +44,6 @@ def generate_page(page_size=20, result_type: ResultType = None): SearchResult( id=fake.unique.name(), result_type=choice((ResultType.DATA_PRODUCT, ResultType.TABLE)), - result_type=( - choice((ResultType.DATA_PRODUCT, ResultType.TABLE)) - if result_type is None - else result_type - ), name=fake.name(), description=fake.paragraph(), metadata={"search_summary": "a"}, diff --git a/tests/selenium/helpers.py b/tests/selenium/helpers.py index 21be4e61..48b10012 100644 --- a/tests/selenium/helpers.py +++ b/tests/selenium/helpers.py @@ -1,7 +1,18 @@ import subprocess -def check_for_accessibility_issues(url): - command = ["npx", "@axe-core/cli", "-q", url] +def check_for_accessibility_issues(url, chromedriver_path=None): + command = ["npx", "@axe-core/cli"] + + if chromedriver_path: + command.extend(["--chromedriver-path", chromedriver_path]) + + command.extend( + [ + "-q", + url, + ] + ) + output = subprocess.run(command, capture_output=True, text=True) assert output.returncode == 0, output.stdout diff --git a/tests/selenium/test_search_scenarios.py b/tests/selenium/test_search_scenarios.py index c8f427e8..c5e04ccc 100644 --- a/tests/selenium/test_search_scenarios.py +++ b/tests/selenium/test_search_scenarios.py @@ -16,13 +16,20 @@ class TestSearchWithoutJavascriptAndCss: @pytest.fixture(autouse=True) def setup( - self, live_server, selenium, home_page, search_page, details_data_product_page + self, + live_server, + selenium, + home_page, + search_page, + details_data_product_page, + chromedriver_path, ): self.selenium = selenium self.live_server_url = live_server.url self.home_page = home_page self.search_page = search_page self.details_data_product_page = details_data_product_page + self.chromedriver_path = chromedriver_path def test_browse_to_first_item_data_product(self, mock_catalogue): """ @@ -160,11 +167,15 @@ def test_clear_all_filters(self): def test_automated_accessibility_home(self): self.start_on_the_home_page() - check_for_accessibility_issues(self.selenium.current_url) + check_for_accessibility_issues( + self.selenium.current_url, chromedriver_path=self.chromedriver_path + ) def test_automated_accessibility_search(self): self.start_on_the_search_page() - check_for_accessibility_issues(self.selenium.current_url) + check_for_accessibility_issues( + self.selenium.current_url, chromedriver_path=self.chromedriver_path + ) def test_search_to_data_product_details(self, mock_catalogue): """ From 83e750874de175f9c4489454e7f2eb3a758907e4 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 19 Feb 2024 15:11:10 +0000 Subject: [PATCH 47/60] update form with updated fields --- home/service/search.py | 1 - home/views.py | 1 + templates/partial/filter1.html | 84 ++++++++++++++++++++++++++++++++++ templates/search.html | 2 +- 4 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 templates/partial/filter1.html diff --git a/home/service/search.py b/home/service/search.py index dc3b223b..fc737350 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -79,7 +79,6 @@ def _get_search_results(self, page: str, items_per_page: int): sort=sort_option, count=items_per_page, ) - return results def _get_paginator(self, items_per_page: int) -> Paginator: diff --git a/home/views.py b/home/views.py index 4be2b8be..64626c5a 100644 --- a/home/views.py +++ b/home/views.py @@ -44,6 +44,7 @@ def dataset_details(request, id): def search_view(request, page: str = "1"): + print(request.GET) new_search = request.GET.get("new", "") if new_search: form = SearchForm() diff --git a/templates/partial/filter1.html b/templates/partial/filter1.html new file mode 100644 index 00000000..d4940961 --- /dev/null +++ b/templates/partial/filter1.html @@ -0,0 +1,84 @@ +{% load future %} +
+
+
+
+

Filter

+
+
+
+
+ +
+
+
+
+

Selected filters

+
+ +
+ {% if form.domains.value %} +

Domain

+ + {% endif %} +
+
+ +
+ + {{form.domain}} + +
+
+ + {{form.subdomains}} +
+
+
+ Security Classification +
+ {% for classification_option in form.classifications %} +
+ {{ classification_option.tag}} + +
+ {% endfor %} +
+
+
+
+
+ Availability +
+ {% for availability_option in form.availabilities %} +
+ {{ availability_option.tag}} + +
+ {% endfor %} +
+
+
+
+
+
+
diff --git a/templates/search.html b/templates/search.html index 358209be..474fcb12 100644 --- a/templates/search.html +++ b/templates/search.html @@ -24,7 +24,7 @@

Find MOJ Data

- {% include "partial/filter.html" %} + {% include "partial/filter1.html" %}

{{total_results|intcomma}} Results

{% include "partial/sort.html" %} From 517f2668e47afccd817e70498e46d0a896765d8e Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 19 Feb 2024 15:11:36 +0000 Subject: [PATCH 48/60] update form with updated fields --- templates/partial/filter.html | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/templates/partial/filter.html b/templates/partial/filter.html index a4c1931a..01c7c862 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -18,7 +18,6 @@

Filter

Domain -<<<<<<< HEAD {{form.domain}}
@@ -44,14 +43,66 @@

Filter

{{ access_option.tag}}
-======= + {% endfor %} +
+ + + + + + +{% load future %} +
+
+
+
+

Filter

+
+
+
+
+ +
+
+
+
+

Selected filters

+
+ +
+ {% if form.domains.value %} +

Domain

+ + {% endif %} +
+
+ +
+
+ Domain
{% for domain_option in form.domains %}
{{ domain_option.tag}}
->>>>>>> 730c59e (Revert template - will add backend later) {% endfor %}
From b4abaede13858fa5adbef5cb3d9d1e5cdc428221 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Tue, 20 Feb 2024 23:01:55 +0000 Subject: [PATCH 49/60] implement custom property search --- home/service/search.py | 38 ++++++++++++++- home/views.py | 2 +- templates/partial/filter.html | 32 ++++++++++--- templates/partial/filter1.html | 84 ---------------------------------- templates/search.html | 2 +- 5 files changed, 64 insertions(+), 94 deletions(-) delete mode 100644 templates/partial/filter1.html diff --git a/home/service/search.py b/home/service/search.py index fc737350..4624bc41 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -73,12 +73,13 @@ def _get_search_results(self, page: str, items_per_page: int): sort_option = None results = self.client.search( - query=query, + query=full_query, page=page_for_search, filters=filter_value, sort=sort_option, count=items_per_page, ) + return results def _get_paginator(self, items_per_page: int) -> Paginator: @@ -129,6 +130,25 @@ def _get_context(self) -> dict[str, Any]: else: page_title = "Search - Data catalogue" + if self.form.is_bound: + label_clear_href = {} + domain = self.form.cleaned_data.get("domain") + subdomain = self.form.cleaned_data.get("subdomains") + if domain: + label_clear_href[domain.split(":")[-1]] = ( + self.form.encode_without_filter( + filter_to_remove=self.form.cleaned_data.get("domain") + ) + ) + if subdomain: + label_clear_href[subdomain.split(":")[-1]] = ( + self.form.encode_without_filter( + filter_to_remove=self.form.cleaned_data.get("subdomains") + ) + ) + else: + label_clear_href = None + print(label_clear_href) context = { "form": self.form, "results": self.results.page_results, @@ -176,3 +196,19 @@ def _get_match_reason_display_names(self): "fieldPaths": "Column name", "fieldDescriptions": "Column description", } + + @staticmethod + def _query_builder(query: str, custom_properties: dict[str, list[str | None]]): + custom_property_query: str = "/q customProperties: " + custom_property_strings: list[str] = [] + + for _, value in custom_properties.items(): + if value: + custom_property_strings.append(" OR ".join(value)) + + if query != "": + custom_property_strings.append(query) + + final_query = " AND ".join(custom_property_strings) + + return f"{custom_property_query} {final_query}" if final_query else "*" diff --git a/home/views.py b/home/views.py index 64626c5a..8e296a58 100644 --- a/home/views.py +++ b/home/views.py @@ -44,7 +44,7 @@ def dataset_details(request, id): def search_view(request, page: str = "1"): - print(request.GET) + # print(request.GET) new_search = request.GET.get("new", "") if new_search: form = SearchForm() diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 01c7c862..1103e1e7 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -71,7 +71,7 @@

Selected filters

Clear filter @@ -94,15 +94,33 @@

Domain

+
+ + {{form.domain}} + +
- Domain + Security Classification
- {% for domain_option in form.domains %} -
- {{ domain_option.tag}} - -
+ {% for classification_option in form.classifications %} +
+ {{ classification_option.tag}} + +
+ {% endfor %} +
+
+
+
+
+ Availability +
+ {% for access_option in form.where_to_access %} +
+ {{ access_option.tag}} + +
{% endfor %}
diff --git a/templates/partial/filter1.html b/templates/partial/filter1.html deleted file mode 100644 index d4940961..00000000 --- a/templates/partial/filter1.html +++ /dev/null @@ -1,84 +0,0 @@ -{% load future %} -
-
-
-
-

Filter

-
-
-
-
- -
-
-
-
-

Selected filters

-
- -
- {% if form.domains.value %} -

Domain

- - {% endif %} -
-
- -
- - {{form.domain}} - -
-
- - {{form.subdomains}} -
-
-
- Security Classification -
- {% for classification_option in form.classifications %} -
- {{ classification_option.tag}} - -
- {% endfor %} -
-
-
-
-
- Availability -
- {% for availability_option in form.availabilities %} -
- {{ availability_option.tag}} - -
- {% endfor %} -
-
-
-
-
-
-
diff --git a/templates/search.html b/templates/search.html index 474fcb12..358209be 100644 --- a/templates/search.html +++ b/templates/search.html @@ -24,7 +24,7 @@

Find MOJ Data

- {% include "partial/filter1.html" %} + {% include "partial/filter.html" %}

{{total_results|intcomma}} Results

{% include "partial/sort.html" %} From 5441f575e8943471c4956caa294cd3cf866e5156 Mon Sep 17 00:00:00 2001 From: Tom Webber Date: Wed, 21 Feb 2024 16:27:19 +0000 Subject: [PATCH 50/60] revert domains (plural) -> domain (singular) changes (may be implemented in later PR) --- home/forms/search.py | 2 +- templates/partial/filter.html | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index 6d1dad96..fe2c971f 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -92,7 +92,7 @@ class SearchForm(forms.Form): required=False, widget=forms.TextInput(attrs={"class": "govuk-input search-input"}), ) - domain = forms.ChoiceField( + domains = forms.MultipleChoiceField( choices=get_domain_choices, required=False, widget=forms.Select( diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 1103e1e7..4292a9a3 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -95,9 +95,17 @@

Domain

Apply filters
- - {{form.domain}} - +
+ Domain +
+ {% for domain_option in form.domains %} +
+ {{ domain_option.tag}} + +
+ {% endfor %} +
+
From 6660d5b262240d48e33505b26c8070299e2c359d Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Thu, 22 Feb 2024 14:42:47 +0000 Subject: [PATCH 51/60] Make domain a single choice field --- home/forms/search.py | 2 +- home/service/search.py | 2 ++ home/views.py | 1 - templates/partial/filter.html | 37 +++++++++++++++++++++-------------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index fe2c971f..6d1dad96 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -92,7 +92,7 @@ class SearchForm(forms.Form): required=False, widget=forms.TextInput(attrs={"class": "govuk-input search-input"}), ) - domains = forms.MultipleChoiceField( + domain = forms.ChoiceField( choices=get_domain_choices, required=False, widget=forms.Select( diff --git a/home/service/search.py b/home/service/search.py index 4624bc41..006baaae 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -131,6 +131,8 @@ def _get_context(self) -> dict[str, Any]: page_title = "Search - Data catalogue" if self.form.is_bound: + domain = self.form.cleaned_data.get("domain", "") + classifications = self.form.cleaned_data.get("classifications", []) label_clear_href = {} domain = self.form.cleaned_data.get("domain") subdomain = self.form.cleaned_data.get("subdomains") diff --git a/home/views.py b/home/views.py index 8e296a58..4be2b8be 100644 --- a/home/views.py +++ b/home/views.py @@ -44,7 +44,6 @@ def dataset_details(request, id): def search_view(request, page: str = "1"): - # print(request.GET) new_search = request.GET.get("new", "") if new_search: form = SearchForm() diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 4292a9a3..04537077 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -52,6 +52,7 @@

Filter

{% load future %} +{% load clear_filter %}
@@ -71,18 +72,29 @@

Selected filters

- {% if form.domains.value %} + {% if label_clear_href|get_item:"domain"|length > 0 %}

Domain

+ {% endif %} + {% if label_clear_href|get_item:"classifications"|length > 0 %} +

Security Classifications

+
    + + {% for label, href in label_clear_href|get_items:"classifications" %}
  • {{label}} Remove this filter
  • @@ -95,17 +107,12 @@

    Domain

    Apply filters
    -
    - Domain -
    - {% for domain_option in form.domains %} -
    - {{ domain_option.tag}} - -
    - {% endfor %} -
    -
    +
    + Domain +
    + {{form.domain}} +
    +
    @@ -127,7 +134,7 @@

    Domain

    {% for access_option in form.where_to_access %}
    {{ access_option.tag}} - +
    {% endfor %}
    From 5348c643c091e25364b0e4a3887fcd2e8b029de6 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:12:07 +0000 Subject: [PATCH 52/60] refactor classifications and where to access string generation, remove full query builder --- home/service/search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/home/service/search.py b/home/service/search.py index 006baaae..902e6702 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -73,7 +73,7 @@ def _get_search_results(self, page: str, items_per_page: int): sort_option = None results = self.client.search( - query=full_query, + query=query, page=page_for_search, filters=filter_value, sort=sort_option, From 962aefd7b45c2b5991b73731bd6f1f5ac816bae6 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:14:06 +0000 Subject: [PATCH 53/60] refactor where to access href creation --- home/service/search.py | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index 902e6702..dbef6a78 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -133,24 +133,45 @@ def _get_context(self) -> dict[str, Any]: if self.form.is_bound: domain = self.form.cleaned_data.get("domain", "") classifications = self.form.cleaned_data.get("classifications", []) + where_to_access = self.form.cleaned_data.get("where_to_access", []) label_clear_href = {} domain = self.form.cleaned_data.get("domain") subdomain = self.form.cleaned_data.get("subdomains") if domain: - label_clear_href[domain.split(":")[-1]] = ( - self.form.encode_without_filter( - filter_to_remove=self.form.cleaned_data.get("domain") + label_clear_href["domain"] = { + domain.split(":")[-1]: ( + self.form.encode_without_filter( + filter_name="domain", filter_value=domain + ) ) - ) - if subdomain: - label_clear_href[subdomain.split(":")[-1]] = ( - self.form.encode_without_filter( - filter_to_remove=self.form.cleaned_data.get("subdomains") + } + if classifications: + classifications_clear_href = {} + for classification in classifications: + classifications_clear_href[classification.split("=")[1]] = ( + self.form.encode_without_filter(classification) ) - ) + label_clear_href["classifications"] = classifications_clear_href + + if where_to_access: + where_to_access_clear_href = {} + for access in where_to_access: + where_to_access_clear_href[access] = ( + self.form.encode_without_filter( + filter_name="where_to_access", filter_value=access + ) + ) + label_clear_href["availability"] = where_to_access_clear_href else: label_clear_href = None - print(label_clear_href) + return label_clear_href + + def _get_context(self) -> dict[str, Any]: + if self.form["query"].value(): + page_title = f'Search for "{self.form["query"].value()}" - Data catalogue' + else: + page_title = "Search - Data catalogue" + context = { "form": self.form, "results": self.results.page_results, From e34a2410f0845f89df5b022ddcc55a2184ad5013 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Sat, 24 Feb 2024 21:18:28 +0000 Subject: [PATCH 54/60] update packages --- package-lock.json | 641 ++++++++++++++++++++++++---------------------- package.json | 1 + 2 files changed, 337 insertions(+), 305 deletions(-) diff --git a/package-lock.json b/package-lock.json index e5cc3a01..dafac93f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,8 @@ "dependencies": { "@babel/preset-env": "^7.23.9", "@ministryofjustice/frontend": "^2.1.0", + "axe": "^12.2.3", + "babel-jest": "^29.7.0", "govuk-frontend": "^5.1.0", "jest-environment-jsdom": "^29.7.0", "sass": "^1.70.0" @@ -2099,313 +2101,342 @@ "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@ladjs/format-util": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@ladjs/format-util/-/format-util-1.0.4.tgz", - "integrity": "sha512-hZere0rUga8kTzSTFbHREXpD9E/jwi94+B5RyLAmMIzl/w/EK1z7rFEnMHzPkU4AZkL42JWSsGXoV8LXMihybg==" - }, - "node_modules/@ministryofjustice/frontend": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-2.1.0.tgz", - "integrity": "sha512-LekTR097OsFku0+sREn7gR3G7UvH7jATw40PvZH4mKtnE8hyyw0gDrCSvFYsRS4kPLDsoFqZ5l0Y3CZE9f364g==", - "dependencies": { - "govuk-frontend": "^5.0.0", - "moment": "^2.27.0" - }, - "engines": { - "node": ">= 4.2.0" - }, - "peerDependencies": { - "jquery": "^3.6.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2""@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0""node": ">=6.9.0" } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/govuk-frontend": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.1.0.tgz", - "integrity": "sha512-Dc3J+uOI4i2VR3BVyfxbf6qVjTT4n4bBqbD0/Io6feP8pt/4IfKdP1vWimZf+BwMKKMXacw10hmdy5UcD6Cr8w==", - "engines": { - "node": ">= 4.2.0" - } - }, - "node_modules/immutable": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/jquery": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", - "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", - "peer": true - }, - "node_modules/moment": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", - "engines": { - "node": "*" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/sass": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", - "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node": ">=6.9.0" + } }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0""@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0""node": ">=6.9.0" + } }, - "engines": { - "node": ">=8.0" + "node_modules/@ladjs/format-util": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@ladjs/format-util/-/format-util-1.0.4.tgz", + "integrity": "sha512-hZere0rUga8kTzSTFbHREXpD9E/jwi94+B5RyLAmMIzl/w/EK1z7rFEnMHzPkU4AZkL42JWSsGXoV8LXMihybg==""node_modules/@ladjs/format-util": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@ladjs/format-util/-/format-util-1.0.4.tgz", + "integrity": "sha512-hZere0rUga8kTzSTFbHREXpD9E/jwi94+B5RyLAmMIzl/w/EK1z7rFEnMHzPkU4AZkL42JWSsGXoV8LXMihybg==" + }, + "node_modules/@ministryofjustice/frontend": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-2.1.0.tgz", + "integrity": "sha512-LekTR097OsFku0+sREn7gR3G7UvH7jATw40PvZH4mKtnE8hyyw0gDrCSvFYsRS4kPLDsoFqZ5l0Y3CZE9f364g==", + "node_modules/@ministryofjustice/frontend": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@ministryofjustice/frontend/-/frontend-2.1.0.tgz", + "integrity": "sha512-LekTR097OsFku0+sREn7gR3G7UvH7jATw40PvZH4mKtnE8hyyw0gDrCSvFYsRS4kPLDsoFqZ5l0Y3CZE9f364g==", + "dependencies": { + "govuk-frontend": "^5.0.0", + "moment": "^2.27.0""govuk-frontend": "^5.0.0", + "moment": "^2.27.0" + }, + "engines": { + "node": ">= 4.2.0" + }, + "peerDependencies": { + "jquery": "^3.6.0""node": ">= 4.2.0" + }, + "peerDependencies": { + "jquery": "^3.6.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/govuk-frontend": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.1.0.tgz", + "integrity": "sha512-Dc3J+uOI4i2VR3BVyfxbf6qVjTT4n4bBqbD0/Io6feP8pt/4IfKdP1vWimZf+BwMKKMXacw10hmdy5UcD6Cr8w==", + "engines": { + "node": ">= 4.2.0" + } + }, + "node_modules/immutable": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/sass": { + "version": "1.70.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", + "integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + } + } } - } - } -} diff --git a/package.json b/package.json index 33321117..9f476312 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "axe": "^12.2.3", "govuk-frontend": "^5.1.0", "jest-environment-jsdom": "^29.7.0", + "axe": "^12.2.3", "sass": "^1.70.0" }, "scripts": { From 35075f8d51231ddae7b9f76596622c3dbf28960e Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 12:01:07 +0000 Subject: [PATCH 55/60] linter updates --- home/service/search.py | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index dbef6a78..123fe842 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -198,7 +198,6 @@ def _highlight_results(self): return highlighted_results else: - pattern = f"({re.escape(query)})" pattern = f"({re.escape(query)})" for result in highlighted_results.page_results: result.description = re.sub( @@ -207,6 +206,7 @@ def _highlight_results(self): result.description, flags=re.IGNORECASE, ) + return highlighted_results def _get_match_reason_display_names(self): @@ -219,19 +219,3 @@ def _get_match_reason_display_names(self): "fieldPaths": "Column name", "fieldDescriptions": "Column description", } - - @staticmethod - def _query_builder(query: str, custom_properties: dict[str, list[str | None]]): - custom_property_query: str = "/q customProperties: " - custom_property_strings: list[str] = [] - - for _, value in custom_properties.items(): - if value: - custom_property_strings.append(" OR ".join(value)) - - if query != "": - custom_property_strings.append(query) - - final_query = " AND ".join(custom_property_strings) - - return f"{custom_property_query} {final_query}" if final_query else "*" From c259e99168d72bc75144272c9451c9ae97b5a86f Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 15:23:20 +0000 Subject: [PATCH 56/60] remove duplicated function --- home/service/search.py | 60 ++++------------------ templates/partial/filter.html | 93 ----------------------------------- tests/conftest.py | 28 +++++++++-- tests/test_views.py | 8 ++- 4 files changed, 39 insertions(+), 150 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index 123fe842..45c5fc13 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -58,7 +58,7 @@ def _get_search_results(self, page: str, items_per_page: int): ) filter_value = [] if domains_and_subdomains: - filter_value.append(MultiSelectFilter("domain", domains_and_subdomains)) + filter_value.append(MultiSelectFilter("domains", domains_and_subdomains)) if classifications: filter_value.append(MultiSelectFilter("customProperties", classifications)) if where_to_access: @@ -104,62 +104,20 @@ def _generate_label_clear_ref(self) -> dict[str, dict[str, str]]: if classifications: classifications_clear_href = {} for classification in classifications: - classifications_clear_href[classification] = ( - self.form.encode_without_filter( - filter_name="classifications", filter_value=classification - ) - ) - label_clear_href["classifications"] = classifications_clear_href - - if where_to_access: - where_to_access_clear_href = {} - for access in where_to_access: - where_to_access_clear_href[access] = ( - self.form.encode_without_filter( - filter_name="where_to_access", filter_value=access - ) - ) - label_clear_href["availability"] = where_to_access_clear_href - else: - label_clear_href = None - return label_clear_href - - def _get_context(self) -> dict[str, Any]: - if self.form["query"].value(): - page_title = f'Search for "{self.form["query"].value()}" - Data catalogue' - else: - page_title = "Search - Data catalogue" - - if self.form.is_bound: - domain = self.form.cleaned_data.get("domain", "") - classifications = self.form.cleaned_data.get("classifications", []) - where_to_access = self.form.cleaned_data.get("where_to_access", []) - label_clear_href = {} - domain = self.form.cleaned_data.get("domain") - subdomain = self.form.cleaned_data.get("subdomains") - if domain: - label_clear_href["domain"] = { - domain.split(":")[-1]: ( - self.form.encode_without_filter( - filter_name="domain", filter_value=domain - ) - ) - } - if classifications: - classifications_clear_href = {} - for classification in classifications: - classifications_clear_href[classification.split("=")[1]] = ( - self.form.encode_without_filter(classification) + classifications_clear_href[ + classification + ] = self.form.encode_without_filter( + filter_name="classifications", filter_value=classification ) label_clear_href["classifications"] = classifications_clear_href if where_to_access: where_to_access_clear_href = {} for access in where_to_access: - where_to_access_clear_href[access] = ( - self.form.encode_without_filter( - filter_name="where_to_access", filter_value=access - ) + where_to_access_clear_href[ + access + ] = self.form.encode_without_filter( + filter_name="where_to_access", filter_value=access ) label_clear_href["availability"] = where_to_access_clear_href else: diff --git a/templates/partial/filter.html b/templates/partial/filter.html index 04537077..e7af7286 100644 --- a/templates/partial/filter.html +++ b/templates/partial/filter.html @@ -51,96 +51,3 @@

    Filter

-{% load future %} -{% load clear_filter %} -
-
-
-
-

Filter

-
-
-
-
- -
-
-
-
-

Selected filters

-
- -
- {% if label_clear_href|get_item:"domain"|length > 0 %} -

Domain

- - {% endif %} - {% if label_clear_href|get_item:"classifications"|length > 0 %} -

Security Classifications

- - {% endif %} -
-
- -
-
- Domain -
- {{form.domain}} -
-
-
-
-
- Security Classification -
- {% for classification_option in form.classifications %} -
- {{ classification_option.tag}} - -
- {% endfor %} -
-
-
-
-
- Availability -
- {% for access_option in form.where_to_access %} -
- {{ access_option.tag}} - -
- {% endfor %} -
-
-
-
-
-
-
diff --git a/tests/conftest.py b/tests/conftest.py index 14c6ce11..26018e00 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,6 +10,10 @@ SearchResponse, SearchResult, ) +from datahub.metadata.schema_classes import ( + DataProductAssociationClass, + DataProductPropertiesClass, +) from django.test import Client from faker import Faker @@ -17,11 +21,6 @@ from home.service.details import DataProductDetailsService from home.service.search import SearchService -from datahub.metadata.schema_classes import ( - DataProductPropertiesClass, - DataProductAssociationClass, -) - fake = Faker() @@ -106,6 +105,25 @@ def mock_search_facets_response(mock_catalogue, domains): mock_catalogue.search_facets.return_value = SearchFacets({"domains": domains}) +def mock_list_data_product_response(mock_catalogue, total_results, page_results=()): + search_response = SearchResponse( + total_results=total_results, page_results=page_results + ) + mock_catalogue.list_data_product_assets.return_value = search_response + + +def mock_get_dataproduct_aspect(mock_catalogue): + data_product_association = DataProductAssociationClass( + destinationUrn="urn:li:dataset:(urn:li:dataPlatform:glue,test.test,PROD)", + sourceUrn="urn:li:dataProduct:test", + ) + + response = DataProductPropertiesClass( + name="test", assets=[data_product_association], description="test" + ) + mock_catalogue.graph.get_aspect.return_value = response + + @pytest.fixture def valid_form(): valid_form = SearchForm( diff --git a/tests/test_views.py b/tests/test_views.py index 8bcbffac..133a5aac 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -34,7 +34,13 @@ def test_bad_form(self, client): class TestDetailsView: def test_details_data_product(self, client): response = client.get( - reverse("home:details", kwargs={"id": "urn:li:dataProduct:common-platform"}) + reverse( + "home:details", + kwargs={ + "id": "urn:li:dataProduct:common-platform", + "result_type": "data_product", + }, + ) ) assert response.status_code == 200 From 14e602f7ecb444473386cc1771ee146d2bb18594 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 15:40:53 +0000 Subject: [PATCH 57/60] update search result ui fields --- templates/partial/search_result.html | 32 ++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/templates/partial/search_result.html b/templates/partial/search_result.html index eb97f27e..50d5386f 100644 --- a/templates/partial/search_result.html +++ b/templates/partial/search_result.html @@ -33,25 +33,43 @@

-
Registered by
+
Registered by:
- {{result.metadata.owner}} + {{result.metadata.maintainer_display_name}}
-
Domain name
+
Database name:
- {{result.metadata.domain_name}} + TBC
-
Last updated date
+
First created:
- {% if result.last_updated %} - {{result.last_updated | date:"jS F Y"}} ({{result.last_updated|naturaltime}}) + {% if result.metadata.creation_date %} + {{result.metadata.creation_date | date:"jS F Y"}} ({{result.metadata.creation_date|naturaltime}}) {% endif %}
+
+
Refresh period:
+
+ TBC +
+
+
+
Retention period:
+
+ {{result.metadata.retention_period_in_days}} +
+
+
+
Domain name
+
+ {{result.metadata.domain_name}} +
+
Tags
From 52ec70f707eecc9d909d6f26bd2cd638e7058e2c Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 15:56:37 +0000 Subject: [PATCH 58/60] fix result type in conftest --- home/forms/search.py | 2 +- home/service/search.py | 12 ++++-------- home/templatetags/lookup.py | 3 ++- tests/conftest.py | 1 - 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/home/forms/search.py b/home/forms/search.py index 6d1dad96..ba9bd468 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -8,7 +8,7 @@ def get_domain_choices() -> list[tuple[str, str]]: """Make API call to obtain domain choices""" # TODO: pull in the domains from the catalogue client # facets = client.search_facets() - # domain_list = facets.options("domain") + # domain_list = facets.options("domains") return [ ("", "All Domains"), ("urn:li:domain:HMCTS", "HMCTS"), diff --git a/home/service/search.py b/home/service/search.py index 45c5fc13..3e9c8a06 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -31,14 +31,10 @@ def __init__(self, form: SearchForm, page: str, items_per_page: int = 20): self.context = self._get_context() @staticmethod - def _build_filter_strings( + def _build_custom_property_filter( filter_param: str, filter_value_list: list[str] ) -> list[str]: - return ( - [f"{filter_param}{filter_value}" for filter_value in filter_value_list] - if filter_value_list - else [] - ) + return [f"{filter_param}{filter_value}" for filter_value in filter_value_list] def _get_search_results(self, page: str, items_per_page: int): if self.form.is_bound: @@ -50,10 +46,10 @@ def _get_search_results(self, page: str, items_per_page: int): sort = form_data.get("sort", "relevance") domain = form_data.get("domain", "") domains_and_subdomains = domains_with_their_subdomains(domain) - classifications = self._build_filter_strings( + classifications = self._build_custom_property_filter( "sensitivityLevel=", form_data.get("classifications", []) ) - where_to_access = self._build_filter_strings( + where_to_access = self._build_custom_property_filter( "whereToAccessDataset=", form_data.get("where_to_access", []) ) filter_value = [] diff --git a/home/templatetags/lookup.py b/home/templatetags/lookup.py index 2f67d140..ea9f839e 100644 --- a/home/templatetags/lookup.py +++ b/home/templatetags/lookup.py @@ -1,5 +1,6 @@ from home.templatetags.markdown import register + @register.filter def lookup(list, lookup_dict): - return sorted([lookup_dict.get(item)for item in list]) + return sorted([lookup_dict.get(item) for item in list]) diff --git a/tests/conftest.py b/tests/conftest.py index 4f723701..167b89ce 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -47,7 +47,6 @@ def generate_page(page_size=20, result_type: ResultType = None): results.append( SearchResult( id=fake.unique.name(), - result_type=choice((ResultType.DATA_PRODUCT, ResultType.TABLE)), result_type=( choice((ResultType.DATA_PRODUCT, ResultType.TABLE)) if result_type is None From 260e14ffc31c34455436f8e1470a46bb9bd6fd75 Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 16:47:50 +0000 Subject: [PATCH 59/60] remove official-sensitive classification --- home/forms/search.py | 1 - 1 file changed, 1 deletion(-) diff --git a/home/forms/search.py b/home/forms/search.py index ba9bd468..66ef02ee 100644 --- a/home/forms/search.py +++ b/home/forms/search.py @@ -73,7 +73,6 @@ def get_sort_choices(): def get_classification_choices(): return [ ("OFFICIAL", "Official"), - ("OFFICIAL-SENSITIVE", "Official-Sensitive"), ("SECRET", "Secret"), ("TOP-SECRET", "Top-Secret"), ] From 84fb52ed034973b0f9330fff5c5b6195e07763fe Mon Sep 17 00:00:00 2001 From: Mitch Dawson Date: Mon, 26 Feb 2024 16:49:21 +0000 Subject: [PATCH 60/60] add Custom Properties match display and rename 'list' to value_list --- home/service/search.py | 1 + home/templatetags/lookup.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/home/service/search.py b/home/service/search.py index 3e9c8a06..48d055c3 100644 --- a/home/service/search.py +++ b/home/service/search.py @@ -172,4 +172,5 @@ def _get_match_reason_display_names(self): "description": "Description", "fieldPaths": "Column name", "fieldDescriptions": "Column description", + "customProperties": "Custom properties", } diff --git a/home/templatetags/lookup.py b/home/templatetags/lookup.py index ea9f839e..998d25e9 100644 --- a/home/templatetags/lookup.py +++ b/home/templatetags/lookup.py @@ -2,5 +2,5 @@ @register.filter -def lookup(list, lookup_dict): - return sorted([lookup_dict.get(item) for item in list]) +def lookup(value_list, lookup_dict): + return sorted([lookup_dict.get(item, "") for item in value_list])

Data Product contentData product content
Table name
{{table.name}}{{table.description}} + {% if table.description|length > 200 %} + {{ table.description|slice:":200"|add:"..."|markdown }} + {% else %} + {{ table.description|markdown }} + {% endif %} + Schema details