diff --git a/compendium_v2/conversion/mapping.py b/compendium_v2/conversion/mapping.py
index 4b9c704bacb9b8d9bc082139cb55c66de3329f51..1258da6c95a6489910d00980879bf13b2f1d9b41 100644
--- a/compendium_v2/conversion/mapping.py
+++ b/compendium_v2/conversion/mapping.py
@@ -10,7 +10,7 @@ WHERE nren_id = {}
                           16426,16429,16430,16432,16433,16434,16435,16438,16439,16446,16448,16449,16450,16451,16452,
                           16453,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,16468,16469,16470,
                           16471,16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,
-                          16486,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16499,16500,16501,16502,
+                          16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16499,16500,16501,16502,
                           16503,16504,16760,16761,16762,16763,16507,16509,16510,16511,16512,16513,16514,16515,16516,
                           16517,16518,16519,16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,
                           16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,
@@ -175,7 +175,7 @@ ID_TO_NAME = {
     16483: "central_procurement_amount",
     16484: "formal_service_management_framework",  # "Yes" "No"
     16485: "service_level_targets",  # "Yes" "No"
-    16486: "service_portfolio_changes",  # "Yes" "No"
+    # 16486: "service_portfolio_changes",  # "Yes" "No"
     16496: "service_portfolio_eosc_portal",  # "Yes" "No"
     16497: "services_on_eosc_portal_list[]:service_name",  # json list with double quotes
     16499: "audits",  # "Yes" "No"
diff --git a/compendium_v2/migrations/surveymodels/survey_model_2022.json b/compendium_v2/migrations/surveymodels/survey_model_2022.json
index e9431ec93f2c0c77bba66014085a2738124859df..7d0ca520bdb71744908da567393a6894b589d7a5 100644
--- a/compendium_v2/migrations/surveymodels/survey_model_2022.json
+++ b/compendium_v2/migrations/surveymodels/survey_model_2022.json
@@ -128,8 +128,8 @@
             {
               "type": "multipletext",
               "name": "staff_employment_type",
-              "title": "What is the number of staff engaged in the NREN activities? ",
-              "description": "Please distinguish permanent and subcontracted using the boxes below. Please put answer in Full Time Equivalent (FTE's).",
+              "title": "What is the number of staff engaged in the NREN activities?",
+              "description": "Please put answer in Full Time Equivalent (FTE's).",
               "items": [
                 {
                   "name": "permanent_fte",
@@ -156,7 +156,7 @@
             {
               "type": "multipletext",
               "name": "staff_roles",
-              "title": "Which of the following functional areas does your NREN have and how much FTE is dedicated to each? ",
+              "title": "How much FTE is devoted to roles in the following functional areas?",
               "items": [
                 {
                   "name": "technical_fte",
@@ -550,7 +550,7 @@
             {
               "type": "text",
               "name": "corporate_strategy_url",
-              "title": "Please provide the URL for your latest corporate strategic plan?",
+              "title": "Please provide the URL for your latest (corporate) strategic plan?",
               "validators": [
                 {
                   "type": "expression",
@@ -616,7 +616,7 @@
                 },
                 {
                   "value": "privacy_notice",
-                  "text": "Organisational privacy notice"
+                  "text": "Organisational Privacy Policy"
                 },
                 {
                   "value": "data_protection_contact",
@@ -673,17 +673,6 @@
               ],
               "showClearButton": true
             },
-            {
-              "type": "radiogroup",
-              "name": "service_portfolio_changes",
-              "title": "Has your NREN made any changes to its service portfolio for its users?",
-              "description": "Please note any changes here and amend the Service Matrix at the last page of this survey",
-              "choices": [
-                "Yes",
-                "No"
-              ],
-              "showClearButton": true
-            },
             {
               "type": "matrixdropdown",
               "name": "service_matrix",
@@ -821,7 +810,7 @@
               "name": "audit_specifics",
               "visibleIf": "{audits} = 'yes'",
               "indent": 1,
-              "title": "Please specify ( for example a certified security auditor on ISO 27001 is performing the audits):"
+              "title": "Please specify (for example a certified security auditor on ISO 27001 is performing the audits):"
             },
             {
               "type": "radiogroup",
@@ -858,7 +847,7 @@
               "choices": [
                 {
                   "value": "geant_workshops",
-                  "text": "We participate in GEANT Crisis workshops such as CLAW"
+                  "text": "We participate in GÉANT Crisis workshops such as CLAW"
                 },
                 {
                   "value": "national_excercises",
@@ -951,7 +940,8 @@
             {
               "type": "matrixdynamic",
               "name": "connected_sites_lists",
-              "title": "Please provide the URLs that lists the sites that are connected to the NREN, if available:",
+              "title": "Please provide the URLs of the webpages listing the institutions or organisations that are connected to the NREN, if available:",
+              "description": "Many NRENs have one or more pages on their website listing user institutions. Please provide these links here if you have them.",
               "columns": [
                 {
                   "name": "connected_sites_url",
@@ -1103,7 +1093,7 @@
               "type": "matrixdropdown",
               "name": "connectivity_level",
               "title": "Level of IP connectivity by Institution type:",
-              "description": "This table explores the average level of connectivity for each type of institution to the NREN. Please enter the typical and the highest capacity at which institutions in this category are connected ( in Mbit/s). As a minimum, please provide this information for Universities and Research institutes.",
+              "description": "This table explores the average level of connectivity for each type of institution to the NREN. Please enter the typical and the highest capacity at which institutions in this category are connected ( in Mbit/s). As a minimum, please provide this information for Universities and Research Institutes.",
               "columns": [
                 {
                   "name": "typical_speed",
@@ -1645,7 +1635,7 @@
               "name": "dark_fibre_lease_kilometers_outside_country",
               "visibleIf": "{dark_fibre_lease} = 'Yes'",
               "indent": 1,
-              "title": "Please state the number of km of such fiber that is outside your country:",
+              "title": "Please state the number of km of such fibre that is outside your country:",
               "validators": [
                 {
                   "type": "numeric",
@@ -1923,8 +1913,8 @@
             {
               "type": "radiogroup",
               "name": "alienwave_services",
-              "title": "Does your NREN make use of alien wavelength/lightpath (AW) services provided by third parties?",
-              "description": "This does not include alien waves (AW) used internally inside your network e.g. coloured optics on routers as they are covered in a later question.",
+              "title": "Does your NREN make use of alien wavelength/lightpath services provided by third parties?",
+              "description": "This does not include alien waves used internally inside your network e.g. coloured optics on routers as they are covered in a later question.",
               "choices": [
                 "Yes",
                 "No",
@@ -1937,7 +1927,7 @@
               "name": "alienwave_services_number",
               "visibleIf": "{alienwave_services} = 'yes'",
               "indent": 1,
-              "title": "Please state the number of individual AW services:",
+              "title": "Please state the number of individual alien wavelength services:",
               "validators": [
                 {
                   "type": "numeric",
@@ -2276,6 +2266,11 @@
     {
       "name": "services",
       "elements": [
+        {
+          "type": "html",
+          "name": "services_hover_explanation",
+          "html": "Descriptions of the individual services are shown if you hover over the service name."
+        },
         {
           "type": "matrixdropdown",
           "name": "services_network",
diff --git a/compendium_v2/migrations/versions/208f6d063905_minor_survey_updates.py b/compendium_v2/migrations/versions/208f6d063905_minor_survey_updates.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7ab9a0b2209bd3b14720f2be0eb83aa941eb75d
--- /dev/null
+++ b/compendium_v2/migrations/versions/208f6d063905_minor_survey_updates.py
@@ -0,0 +1,2978 @@
+"""minor survey updates
+
+Revision ID: 208f6d063905
+Revises: 6f2953f986d0
+Create Date: 2023-08-18 16:15:37.783913
+
+"""
+
+# flake8: noqa
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '208f6d063905'
+down_revision = '6f2953f986d0'
+branch_labels = None
+depends_on = None
+
+
+new_survey_model = """
+{
+  "title": "Compendium",
+  "logoPosition": "right",
+  "pages": [
+    {
+      "name": "organization",
+      "elements": [
+        {
+          "type": "panel",
+          "name": "panel1",
+          "elements": [
+            {
+              "type": "text",
+              "name": "budget",
+              "title": "What is your NRENs budget for {previousyear} or {previousyear}/{surveyyear} in million euro?",
+              "description": "If your budget is not per calendar year, please provide figures for the budget that covers the largest part of {previousyear} including GEANT subsidy.",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                }
+              ]
+            },
+            {
+              "type": "multipletext",
+              "name": "income_sources",
+              "title": "Estimate (in % of income) the sources of your NREN-related income for {previousyear} or {previousyear}/{surveyyear}.",
+              "description": "European Funding should include GÉANT funding.",
+              "validators": [
+                {
+                  "type": "expression",
+                  "text": "The percentages should add up to 100",
+                  "expression": "(sum({income_sources.client_institutions}, {income_sources.gov_public_bodies}, {income_sources.european_funding}, {income_sources.commercial}, {income_sources.other}) = 100) or ({income_sources} empty)"
+                }
+              ],
+              "items": [
+                {
+                  "name": "client_institutions",
+                  "title": "Client institutions (universities/schools/research institutes/commercial/other)",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                },
+                {
+                  "name": "gov_public_bodies",
+                  "title": "Government/public bodies",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                },
+                {
+                  "name": "european_funding",
+                  "title": "European funding",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                },
+                {
+                  "name": "commercial",
+                  "title": "Commercial services (e.g. domain reg, security)",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                },
+                {
+                  "name": "other",
+                  "title": "Other",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                }
+              ]
+            },
+            {
+              "type": "dropdown",
+              "name": "charging_mechanism",
+              "title": "How do you charge your client institutions?",
+              "choices": [
+                {
+                  "value": "no_charge",
+                  "text": "We do not charge them directly"
+                },
+                {
+                  "value": "flat_fee",
+                  "text": "We charge a flat fee, based on bandwidth"
+                },
+                {
+                  "value": "usage_based_fee",
+                  "text": "We charge a usage-based fee"
+                },
+                {
+                  "value": "combination",
+                  "text": "We use a combination of flat fee and usage-based fee"
+                },
+                {
+                  "value": "other",
+                  "text": "Other"
+                }
+              ]
+            }
+          ],
+          "title": "Budget, Income and Billing"
+        },
+        {
+          "type": "panel",
+          "name": "staff",
+          "elements": [
+            {
+              "type": "multipletext",
+              "name": "staff_employment_type",
+              "title": "What is the number of staff engaged in the NREN activities?",
+              "description": "Please put answer in Full Time Equivalent (FTE's).",
+              "items": [
+                {
+                  "name": "permanent_fte",
+                  "title": "Permanent staff",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                },
+                {
+                  "name": "subcontracted_fte",
+                  "title": "Subcontracted staff",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                }
+              ]
+            },
+            {
+              "type": "multipletext",
+              "name": "staff_roles",
+              "title": "How much FTE is devoted to roles in the following functional areas?",
+              "items": [
+                {
+                  "name": "technical_fte",
+                  "title": "Technical roles",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                },
+                {
+                  "name": "nontechnical_fte",
+                  "title": "Non-technical roles",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "parent_organization",
+              "title": "Is your NREN part of a larger organisation (e.g. ministry, university)?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "parent_organization_name",
+              "visibleIf": "{parent_organization} = 'Yes'",
+              "indent": 1,
+              "title": "What is the name of this larger organisation?"
+            },
+            {
+              "type": "radiogroup",
+              "name": "suborganizations",
+              "title": "Does your NREN have sub-organisations?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "suborganization_details",
+              "visibleIf": "{suborganizations} = 'Yes'",
+              "indent": 1,
+              "title": "Please fill in the details:",
+              "columns": [
+                {
+                  "name": "suborganization_name",
+                  "title": "Name of your sub-organisation?",
+                  "cellType": "text",
+                  "isRequired": true
+                },
+                {
+                  "name": "suborganization_role",
+                  "title": "Role of your sub-organisation?",
+                  "cellType": "dropdown",
+                  "choices": [
+                    {
+                      "value": "idc",
+                      "text": "IDC federation"
+                    },
+                    {
+                      "value": "hpc",
+                      "text": "HPC centre"
+                    }
+                  ],
+                  "showOtherItem": true
+                }
+              ],
+              "rowCount": 1,
+              "maxRowCount": 30
+            },
+            {
+              "type": "radiogroup",
+              "name": "ec_projects",
+              "title": "Other than GÉANT, is your NREN involved in other EC projects?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "ec_project_names",
+              "visibleIf": "{ec_projects} = 'Yes'",
+              "indent": 1,
+              "title": "Please list the name of the projects",
+              "description": "Use one line per project.",
+              "columns": [
+                {
+                  "name": "ec_project_name",
+                  "title": "Project name",
+                  "cellType": "text"
+                }
+              ],
+              "rowCount": 1
+            }
+          ],
+          "title": "Staff and Projects"
+        },
+        {
+          "type": "panel",
+          "name": "basic_information",
+          "elements": [
+            {
+              "type": "text",
+              "name": "full_name_english",
+              "title": "Full name of the organisation (in English):"
+            },
+            {
+              "type": "text",
+              "name": "full_name_national_languages",
+              "title": "Full name of the organisation in the national language(s):",
+              "description": "Please use the Latin alphabet."
+            },
+            {
+              "type": "text",
+              "name": "abbreviation_english",
+              "title": "Abbreviation in English (if applicable):",
+              "description": "Please always provide this information."
+            },
+            {
+              "type": "text",
+              "name": "abbreviation_national_languages",
+              "title": "Abbreviation in the national language(s) (if applicable):",
+              "description": "Please always provide this information. Please use the Latin alphabet."
+            },
+            {
+              "type": "text",
+              "name": "street_name_and_number",
+              "title": "Number and street name:"
+            },
+            {
+              "type": "text",
+              "name": "city",
+              "title": "Postal town (county):"
+            },
+            {
+              "type": "text",
+              "name": "postal_code",
+              "title": "Postal Code:"
+            },
+            {
+              "type": "dropdown",
+              "name": "country",
+              "title": "Country:",
+              "choices": [
+                "Afghanistan",
+                "Albania",
+                "Algeria",
+                "Angola",
+                "Argentina",
+                "Armenia",
+                "Australia",
+                "Austria",
+                "Azerbaijan",
+                "Bahamas",
+                "Bahrain",
+                "Bangladesh",
+                "Barbados",
+                "Belarus",
+                "Belgium",
+                "Belize",
+                "Benin",
+                "Bermuda",
+                "Bhutan",
+                "Bolivia",
+                "Bosnia And Herzegowina",
+                "Botswana",
+                "Brazil",
+                "Brunei Darussalam",
+                "Bulgaria",
+                "Burkina Faso",
+                "Burundi",
+                "Cambodia",
+                "Cameroon",
+                "Canada",
+                "Cape Verde",
+                "Chad",
+                "Chile",
+                "China",
+                "Colombia",
+                "Congo",
+                "Congo, The Democratic Republic Of The",
+                "Costa Rica",
+                "Cote D'ivoire",
+                "Croatia",
+                "Cuba",
+                "Cyprus",
+                "Czech Republic",
+                "Denmark",
+                "Dominican Republic",
+                "Ecuador",
+                "Egypt",
+                "El Salvador",
+                "Estonia",
+                "Ethiopia",
+                "Fiji",
+                "Finland",
+                "France",
+                "Gabon",
+                "Gambia",
+                "Georgia",
+                "Germany",
+                "Ghana",
+                "Greece",
+                "Grenada",
+                "Guatemala",
+                "Guinea",
+                "Guyana",
+                "Haiti",
+                "Honduras",
+                "Hong Kong",
+                "Hungary",
+                "Iceland",
+                "India",
+                "Indonesia",
+                "Iran (islamic Republic Of)",
+                "Iraq",
+                "Ireland",
+                "Israel",
+                "Italy",
+                "Jamaica",
+                "Japan",
+                "Jordan",
+                "Kazakhstan",
+                "Kenya",
+                "Korea, Republic Of",
+                "Kuwait",
+                "Kyrgyzstan",
+                "Lao People's Democratic Republic",
+                "Latvia",
+                "Lebanon",
+                "Lesotho",
+                "Liberia",
+                "Libyan Arab Jamahiriya",
+                "Lithuania",
+                "Luxembourg",
+                "Macedonia, North",
+                "Madagascar",
+                "Malawi",
+                "Malaysia",
+                "Mali",
+                "Malta",
+                "Mauritania",
+                "Mauritius",
+                "Mexico",
+                "Micronesia, Federated States Of",
+                "Moldova, Republic Of",
+                "Mongolia",
+                "Montenegro",
+                "Morocco",
+                "Mozambique",
+                "Myanmar",
+                "Namibia",
+                "Nepal",
+                "Netherlands",
+                "New Zealand",
+                "Nicaragua",
+                "Niger",
+                "Nigeria",
+                "Norway",
+                "Oman",
+                "Pakistan",
+                "Palestine",
+                "Panama",
+                "Papua New Guinea",
+                "Paraguay",
+                "Peru",
+                "Philippines",
+                "Poland",
+                "Portugal",
+                "Puerto Rico",
+                "Qatar",
+                "Romania",
+                "Russian Federation",
+                "Rwanda",
+                "Samoa",
+                "Saudi Arabia",
+                "Senegal",
+                "Serbia",
+                "Serbia",
+                "Singapore",
+                "Slovakia (Slovak Republic)",
+                "Slovenia",
+                "Somalia",
+                "South Africa",
+                "South Sudan",
+                "Spain",
+                "Sri Lanka",
+                "Sudan",
+                "Suriname",
+                "Sweden",
+                "Switzerland",
+                "Syrian Arab Republic",
+                "Taiwan",
+                "Tajikistan",
+                "Tanzania, United Republic Of",
+                "Thailand",
+                "Togo",
+                "Trinidad And Tobago",
+                "Tunisia",
+                "Turkey",
+                "Turkmenistan",
+                "Uganda",
+                "Ukraine",
+                "United Arab Emirates",
+                "United Kingdom",
+                "United Kingdom",
+                "United States",
+                "Uruguay",
+                "Uzbekistan",
+                "Venezuela",
+                "Vietnam",
+                "Virgin Islands (british)",
+                "Yemen",
+                "Zambia",
+                "Zimbabwe"
+              ]
+            },
+            {
+              "type": "text",
+              "name": "phone_number",
+              "title": "Phone number:",
+              "inputType": "tel"
+            },
+            {
+              "type": "text",
+              "name": "email_address",
+              "title": "General email address:",
+              "validators": [
+                {
+                  "type": "email"
+                }
+              ],
+              "inputType": "email"
+            },
+            {
+              "type": "text",
+              "name": "website",
+              "title": "Website:",
+              "validators": [
+                {
+                  "type": "expression",
+                  "text": "Please provide a single valid website url including http:// or https://",
+                  "expression": "validateWebsiteUrl({website})"
+                }
+              ],
+              "inputType": "url"
+            }
+          ],
+          "title": "Basic Information"
+        },
+        {
+          "type": "comment",
+          "name": "organization_comments",
+          "title": "Comments regarding this section:"
+        }
+      ],
+      "title": "Organisation"
+    },
+    {
+      "name": "standards_and_policies",
+      "elements": [
+        {
+          "type": "panel",
+          "name": "policy",
+          "elements": [
+            {
+              "type": "radiogroup",
+              "name": "corporate_strategy",
+              "title": "Have you made any updates to your corporate strategy over the last year?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "corporate_strategy_url",
+              "title": "Please provide the URL for your latest (corporate) strategic plan?",
+              "validators": [
+                {
+                  "type": "expression",
+                  "text": "Please provide a single valid website url including http:// or https://",
+                  "expression": "validateWebsiteUrl({corporate_strategy_url})"
+                }
+              ],
+              "inputType": "url"
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "policies",
+              "title": "Does your NREN have the following policies?",
+              "hideCheckboxLabels": true,
+              "columns": [
+                {
+                  "name": "available",
+                  "title": "Policy available",
+                  "cellType": "checkbox",
+                  "choices": [
+                    {
+                      "value": "yes",
+                      "text": "Yes"
+                    }
+                  ]
+                },
+                {
+                  "name": "url",
+                  "title": "Please provide the URL",
+                  "cellType": "text",
+                  "visibleIf": "{row.available} = ['yes']",
+                  "validators": [
+                    {
+                      "type": "expression",
+                      "text": "Please provide a single valid website url including http:// or https://",
+                      "expression": "validateWebsiteUrl({row.url})"
+                    }
+                  ],
+                  "inputType": "url"
+                }
+              ],
+              "cellType": "checkbox",
+              "rows": [
+                {
+                  "value": "environmental_policy",
+                  "text": "Environmental Policy"
+                },
+                {
+                  "value": "equal_opportunity_policy",
+                  "text": "Equality Opportunity Policy"
+                },
+                {
+                  "value": "gender_equality_policy",
+                  "text": "Gender Equality Policy"
+                },
+                {
+                  "value": "connectivity_policy",
+                  "text": "Connectivity Policy"
+                },
+                {
+                  "value": "acceptable_use_policy",
+                  "text": "Acceptable Use Policy (AUP)"
+                },
+                {
+                  "value": "privacy_notice",
+                  "text": "Organisational Privacy Policy"
+                },
+                {
+                  "value": "data_protection_contact",
+                  "text": "Dedicated contact for data protection, privacy or GDPR queries"
+                }
+              ],
+              "rowTitleWidth": "20%"
+            },
+            {
+              "type": "radiogroup",
+              "name": "central_software_procurement",
+              "title": "Do you centrally procure software for your customers?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "central_procurement_amount",
+              "visibleIf": "{central_software_procurement} = 'yes'",
+              "indent": 1,
+              "title": "What is the total amount (in Euro) that you procured in {previousyear} or {previousyear}/{surveyyear} on behalf of your customers?",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                },
+                {
+                  "type": "regex",
+                  "text": "Please round to a whole number",
+                  "regex": "^[0-9]*$"
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "formal_service_management_framework",
+              "title": "Does your NREN operate a formal service management framework for all of your services?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "radiogroup",
+              "name": "service_level_targets",
+              "title": "Are Service Level Targets available for your NREN services?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "service_matrix",
+              "title": "Which service types are available for which user types?",
+              "columns": [
+                {
+                  "name": "service_types",
+                  "title": "Service types",
+                  "cellType": "checkbox",
+                  "showInMultipleColumns": true,
+                  "choices": [
+                    {
+                      "value": "network_services",
+                      "text": "Network services"
+                    },
+                    {
+                      "value": "isp_support",
+                      "text": "ISP support"
+                    },
+                    {
+                      "value": "security",
+                      "text": "Security"
+                    },
+                    {
+                      "value": "identity",
+                      "text": "Identity/T&I"
+                    },
+                    {
+                      "value": "collaboration",
+                      "text": "Collaboration"
+                    },
+                    {
+                      "value": "multimedia",
+                      "text": "Multimedia"
+                    },
+                    {
+                      "value": "storage_and_hosting",
+                      "text": "Storage and Hosting"
+                    },
+                    {
+                      "value": "professional_services",
+                      "text": "Professional services"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "universities",
+                  "text": "Universities & Other (ISCED 6-8)"
+                },
+                {
+                  "value": "further_education",
+                  "text": "Further education (ISCED 4-5)"
+                },
+                {
+                  "value": "secondary_schools",
+                  "text": "Secondary schools (ISCED 2-3)"
+                },
+                {
+                  "value": "primary_schools",
+                  "text": "Primary schools (ISCED 1)"
+                },
+                {
+                  "value": "institutes",
+                  "text": "Research Institutes"
+                },
+                {
+                  "value": "cultural",
+                  "text": "Libraries, Museums, Archives, Cultural institutions"
+                },
+                {
+                  "value": "hospitals",
+                  "text": "Non-university public Hospitals"
+                },
+                {
+                  "value": "government",
+                  "text": "Government departments (national, regional, local)"
+                },
+                {
+                  "value": "iros",
+                  "text": "International (virtual) research organisations"
+                },
+                {
+                  "value": "for_profit_orgs",
+                  "text": "For-profit organisations"
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "service_portfolio_eosc_portal",
+              "title": "Are any of the services in your service portfolio listed on the EOSC portal?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "services_on_eosc_portal_list",
+              "visibleIf": "{service_portfolio_eosc_portal} = 'Yes'",
+              "indent": 1,
+              "title": "Can you list them?",
+              "columns": [
+                {
+                  "name": "service_name",
+                  "title": "Service name",
+                  "cellType": "text"
+                }
+              ],
+              "rowCount": 1,
+              "maxRowCount": 50
+            }
+          ],
+          "title": "Policy & Portfolio"
+        },
+        {
+          "type": "panel",
+          "name": "standards",
+          "elements": [
+            {
+              "type": "radiogroup",
+              "name": "audits",
+              "title": "Do you have external or internal audits of your information security management systems e.g. risk management and policies?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "audit_specifics",
+              "visibleIf": "{audits} = 'yes'",
+              "indent": 1,
+              "title": "Please specify (for example a certified security auditor on ISO 27001 is performing the audits):"
+            },
+            {
+              "type": "radiogroup",
+              "name": "business_continuity_plans",
+              "title": "Do you have Business Continuity plans in place to ensure business continuation and operations?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "business_continuity_plans_specifics",
+              "visibleIf": "{business_continuity_plans} = 'yes'",
+              "indent": 1,
+              "title": "Please specify if you comply with any international standard and if you test the continuity plans regularly."
+            },
+            {
+              "type": "radiogroup",
+              "name": "crisis_management_procedure",
+              "title": "Does your NREN have a formal crisis management procedure?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "checkbox",
+              "name": "crisis_exercises",
+              "title": "Does your NREN run or participate in crisis exercises to test procedures and train employees?",
+              "description": "Multiple answers possible, in the last 12 months",
+              "choices": [
+                {
+                  "value": "geant_workshops",
+                  "text": "We participate in GÉANT Crisis workshops such as CLAW"
+                },
+                {
+                  "value": "national_excercises",
+                  "text": "We participated in National crisis exercises "
+                },
+                {
+                  "value": "tabletop_exercises",
+                  "text": "We run our own tabletop exercises"
+                },
+                {
+                  "value": "simulation_excercises",
+                  "text": "We run our own simulation exercises"
+                },
+                {
+                  "value": "other_excercises",
+                  "text": " We have done/participated in other exercises or trainings"
+                },
+                {
+                  "value": "real_crisis",
+                  "text": "We had a real crisis"
+                },
+                {
+                  "value": "none",
+                  "text": "No, we have not done any crisis exercises or trainings"
+                }
+              ]
+            },
+            {
+              "type": "checkbox",
+              "name": "security_controls",
+              "title": "Do you utilise security controls such as anti-virus, integrity checkers and systemic firewalls to protect your assets?",
+              "choices": [
+                {
+                  "value": "anti_virus",
+                  "text": "Anti Virus"
+                },
+                {
+                  "value": "anti_spam",
+                  "text": "Anti-Spam"
+                },
+                {
+                  "value": "firewall",
+                  "text": "Firewall"
+                },
+                {
+                  "value": "ddos_mitigation",
+                  "text": "DDoS mitigation"
+                },
+                {
+                  "value": "monitoring",
+                  "text": "Network monitoring"
+                },
+                {
+                  "value": "ips_ids",
+                  "text": "IPS/IDS"
+                },
+                {
+                  "value": "acl",
+                  "text": "ACL"
+                },
+                {
+                  "value": "segmentation",
+                  "text": "Network segmentation"
+                },
+                {
+                  "value": "integrity_checking",
+                  "text": "Integrity checking"
+                }
+              ],
+              "showOtherItem": true
+            }
+          ],
+          "title": "Standards"
+        },
+        {
+          "type": "comment",
+          "name": "policy_comments",
+          "title": "Comments regarding this section:"
+        }
+      ],
+      "title": "Standards & Policies"
+    },
+    {
+      "name": "connected_users",
+      "elements": [
+        {
+          "type": "panel",
+          "name": "panel2",
+          "elements": [
+            {
+              "type": "matrixdynamic",
+              "name": "connected_sites_lists",
+              "title": "Please provide the URLs of the webpages listing the institutions or organisations that are connected to the NREN, if available:",
+              "description": "Many NRENs have one or more pages on their website listing user institutions. Please provide these links here if you have them.",
+              "columns": [
+                {
+                  "name": "connected_sites_url",
+                  "title": "Url:",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "expression",
+                      "text": "Please provide a single valid website url including http:// or https://",
+                      "expression": "validateWebsiteUrl({row.connected_sites_url})"
+                    }
+                  ],
+                  "inputType": "url"
+                }
+              ],
+              "rowCount": 1,
+              "maxRowCount": 50
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "connectivity_proportions",
+              "title": "Please give an estimate of the proportion of the institutions in each category for which your NREN provides IP connectivity: ",
+              "description": "For the questions in this section, please use the ISCED 2011 classification system (the UNESCO scheme for International Standard Classification of Education) as follows: * Level 8 - Doctorate or equivalent level * Level 7 - Masters or equivalent level * Level 6 - Bachelors or equivalent level * Level 5 - Short-cycle tertiary education * Level 4 - Post-secondary non-tertiary education. This can include, for example, short vocational training programmes * Levels 2 and 3: Secondary education * Level 1: Primary or basic education * Level 0: Pre-primary education",
+              "columns": [
+                {
+                  "name": "covered",
+                  "title": "Does your remit cover connectivity to this institution type:",
+                  "cellType": "dropdown",
+                  "choices": [
+                    {
+                      "value": "yes_incl_other",
+                      "text": "Yes - including transit to other networks"
+                    },
+                    {
+                      "value": "yes_national_nren",
+                      "text": "Yes - national NREN access"
+                    },
+                    {
+                      "value": "sometimes",
+                      "text": "In some circumstances"
+                    },
+                    {
+                      "value": "no_policy",
+                      "text": "No - not eligible for policy reasons"
+                    },
+                    {
+                      "value": "no_financial",
+                      "text": "No - financial restrictions (NREN is unable to charge/cover costs)"
+                    },
+                    {
+                      "value": "no_other",
+                      "text": "No - other reason"
+                    },
+                    {
+                      "value": "unsure",
+                      "text": "Unsure/unclear"
+                    }
+                  ]
+                },
+                {
+                  "name": "nr_connected",
+                  "title": "Number of institutions connected in this category (actual number):",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please use a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                },
+                {
+                  "name": "market_share_percentage",
+                  "title": "% market share of institutions connected in this category:",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                },
+                {
+                  "name": "nr_of_users",
+                  "title": "Number of users served in this category (actual number):",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please use a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "universities",
+                  "text": "Universities & Other (ISCED 6-8)"
+                },
+                {
+                  "value": "further_education",
+                  "text": "Further education (ISCED 4-5)"
+                },
+                {
+                  "value": "secondary_schools",
+                  "text": "Secondary schools (ISCED 2-3)"
+                },
+                {
+                  "value": "primary_schools",
+                  "text": "Primary schools (ISCED 1)"
+                },
+                {
+                  "value": "institutes",
+                  "text": "Research Institutes"
+                },
+                {
+                  "value": "cultural",
+                  "text": "Libraries, Museums, Archives, Cultural institutions"
+                },
+                {
+                  "value": "hospitals",
+                  "text": "Non-university public Hospitals"
+                },
+                {
+                  "value": "government",
+                  "text": "Government departments (national, regional, local)"
+                },
+                {
+                  "value": "iros",
+                  "text": "International (virtual) research organisations"
+                },
+                {
+                  "value": "for_profit_orgs",
+                  "text": "For-profit organisations"
+                }
+              ]
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "connectivity_level",
+              "title": "Level of IP connectivity by Institution type:",
+              "description": "This table explores the average level of connectivity for each type of institution to the NREN. Please enter the typical and the highest capacity at which institutions in this category are connected ( in Mbit/s). As a minimum, please provide this information for Universities and Research Institutes.",
+              "columns": [
+                {
+                  "name": "typical_speed",
+                  "title": "Typical link speed (Mbit/s):",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please use a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                },
+                {
+                  "name": "highest_speed",
+                  "title": "Highest speed link (Mbit/s):",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please use a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                },
+                {
+                  "name": "highest_speed_connection_percentage",
+                  "title": "Proportionally how many institutions in this category are connected at the highest capacity? (%):",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "universities",
+                  "text": "Universities & Other (ISCED 6-8)"
+                },
+                {
+                  "value": "further_education",
+                  "text": "Further education (ISCED 4-5)"
+                },
+                {
+                  "value": "secondary_schools",
+                  "text": "Secondary schools (ISCED 2-3)"
+                },
+                {
+                  "value": "primary_schools",
+                  "text": "Primary schools (ISCED 1)"
+                },
+                {
+                  "value": "institutes",
+                  "text": "Research Institutes"
+                },
+                {
+                  "value": "cultural",
+                  "text": "Libraries, Museums, Archives, Cultural institutions"
+                },
+                {
+                  "value": "hospitals",
+                  "text": "Non-university public Hospitals"
+                },
+                {
+                  "value": "government",
+                  "text": "Government departments (national, regional, local)"
+                },
+                {
+                  "value": "iros",
+                  "text": "International (virtual) research organisations"
+                },
+                {
+                  "value": "for_profit_orgs",
+                  "text": "For-profit organisations"
+                }
+              ]
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "traffic_carriers",
+              "title": "How is the traffic carried?",
+              "columns": [
+                {
+                  "name": "carry_mechanism",
+                  "title": "Carry mechanism",
+                  "cellType": "dropdown",
+                  "choices": [
+                    {
+                      "value": "nren_local_loops",
+                      "text": "NREN provides the local loops"
+                    },
+                    {
+                      "value": "regional_nren_backbone",
+                      "text": "Traffic carried to the backbone by regional NREN"
+                    },
+                    {
+                      "value": "commercial_provider_backbone",
+                      "text": "Traffic carried to the backbone by commercial providers"
+                    },
+                    {
+                      "value": "man",
+                      "text": "MAN"
+                    },
+                    {
+                      "value": "other",
+                      "text": "Other"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "universities",
+                  "text": "Universities & Other (ISCED 6-8)"
+                },
+                {
+                  "value": "further_education",
+                  "text": "Further education (ISCED 4-5)"
+                },
+                {
+                  "value": "secondary_schools",
+                  "text": "Secondary schools (ISCED 2-3)"
+                },
+                {
+                  "value": "primary_schools",
+                  "text": "Primary schools (ISCED 1)"
+                },
+                {
+                  "value": "institutes",
+                  "text": "Research Institutes"
+                },
+                {
+                  "value": "cultural",
+                  "text": "Libraries, Museums, Archives, Cultural institutions"
+                },
+                {
+                  "value": "hospitals",
+                  "text": "Non-university public Hospitals"
+                },
+                {
+                  "value": "government",
+                  "text": "Government departments (national, regional, local)"
+                },
+                {
+                  "value": "iros",
+                  "text": "International (virtual) research organisations"
+                },
+                {
+                  "value": "for_profit_orgs",
+                  "text": "For-profit organisations"
+                }
+              ]
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "traffic_load",
+              "title": "What are the traffic loads in Mbit/s?",
+              "columns": [
+                {
+                  "name": "average_from_institutions_to_network",
+                  "title": "Average load from institutions to the network",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please round to a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                },
+                {
+                  "name": "average_to_institutions_from_network",
+                  "title": "Average load to institutions from the network",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please round to a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                },
+                {
+                  "name": "peak_from_institutions_to_network",
+                  "title": "Peak load from institutions to the network",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please round to a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                },
+                {
+                  "name": "peak_to_institutions_from_network",
+                  "title": "Peak load to institutions from the network",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    },
+                    {
+                      "type": "regex",
+                      "text": "Please round to a whole number",
+                      "regex": "^[0-9]*$"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "universities",
+                  "text": "Universities & Other (ISCED 6-8)"
+                },
+                {
+                  "value": "further_education",
+                  "text": "Further education (ISCED 4-5)"
+                },
+                {
+                  "value": "secondary_schools",
+                  "text": "Secondary schools (ISCED 2-3)"
+                },
+                {
+                  "value": "primary_schools",
+                  "text": "Primary schools (ISCED 1)"
+                },
+                {
+                  "value": "institutes",
+                  "text": "Research Institutes"
+                },
+                {
+                  "value": "cultural",
+                  "text": "Libraries, Museums, Archives, Cultural institutions"
+                },
+                {
+                  "value": "hospitals",
+                  "text": "Non-university public Hospitals"
+                },
+                {
+                  "value": "government",
+                  "text": "Government departments (national, regional, local)"
+                },
+                {
+                  "value": "iros",
+                  "text": "International (virtual) research organisations"
+                },
+                {
+                  "value": "for_profit_orgs",
+                  "text": "For-profit organisations"
+                }
+              ]
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "traffic_growth",
+              "title": "What do you expect the traffic growth to be in the next 3 years?",
+              "columns": [
+                {
+                  "name": "growth_rate",
+                  "title": "% growth",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "universities",
+                  "text": "Universities & Other (ISCED 6-8)"
+                },
+                {
+                  "value": "further_education",
+                  "text": "Further education (ISCED 4-5)"
+                },
+                {
+                  "value": "secondary_schools",
+                  "text": "Secondary schools (ISCED 2-3)"
+                },
+                {
+                  "value": "primary_schools",
+                  "text": "Primary schools (ISCED 1)"
+                },
+                {
+                  "value": "institutes",
+                  "text": "Research Institutes"
+                },
+                {
+                  "value": "cultural",
+                  "text": "Libraries, Museums, Archives, Cultural institutions"
+                },
+                {
+                  "value": "hospitals",
+                  "text": "Non-university public Hospitals"
+                },
+                {
+                  "value": "government",
+                  "text": "Government departments (national, regional, local)"
+                },
+                {
+                  "value": "iros",
+                  "text": "International (virtual) research organisations"
+                },
+                {
+                  "value": "for_profit_orgs",
+                  "text": "For-profit organisations"
+                }
+              ]
+            }
+          ],
+          "title": "CONNECTED USERS"
+        },
+        {
+          "type": "panel",
+          "name": "connected_users_commercial",
+          "elements": [
+            {
+              "type": "matrixdropdown",
+              "name": "commercial_organizations",
+              "title": "What types of commercial organisations do you connect?",
+              "columns": [
+                {
+                  "name": "connection",
+                  "title": "Connection",
+                  "cellType": "dropdown",
+                  "choices": [
+                    {
+                      "value": "yes_incl_other",
+                      "text": "Yes - Including transit to other networks"
+                    },
+                    {
+                      "value": "yes_national_nren",
+                      "text": "Yes - National NREN access only"
+                    },
+                    {
+                      "value": "yes_if_sponsored",
+                      "text": "Yes - only if sponsored by a connected institution"
+                    },
+                    {
+                      "value": "no_but_direct_peering",
+                      "text": "No - but we offer a direct or IX peering"
+                    },
+                    {
+                      "value": "no_policy",
+                      "text": "No - not eligible for policy reasons"
+                    },
+                    {
+                      "value": "no_financial",
+                      "text": "No - financial restrictions (NREN is unable to charge/recover costs)"
+                    },
+                    {
+                      "value": "no_other",
+                      "text": "No - other reason / unsure"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "commercial_r_e",
+                  "text": "Commercial R&E traffic only"
+                },
+                {
+                  "value": "commercial_general",
+                  "text": "Commercial general"
+                },
+                {
+                  "value": "commercial_collaboration",
+                  "text": "Commercial for collaboration only (project/time limited)"
+                },
+                {
+                  "value": "commercial_service_provider",
+                  "text": "Commercial Service Provider"
+                },
+                {
+                  "value": "university_spin_off",
+                  "text": "University Spin Off/Incubator"
+                }
+              ]
+            },
+            {
+              "type": "matrixdropdown",
+              "name": "commercial_charging_levels",
+              "title": "What are the typical charging levels for the following types of commercial connections? Please tick all that apply:",
+              "columns": [
+                {
+                  "name": "charging_level",
+                  "title": "Charging level",
+                  "cellType": "dropdown",
+                  "choices": [
+                    {
+                      "value": "higher_than_r_e_charges",
+                      "text": "Charges typically higher than for R&E users"
+                    },
+                    {
+                      "value": "same_as_r_e_charges",
+                      "text": "Same charging model as for R&E users"
+                    },
+                    {
+                      "value": "no_charges_if_r_e_requested",
+                      "text": "No charges applied if requested by R&E users"
+                    },
+                    {
+                      "value": "lower_than_r_e_charges",
+                      "text": "Charges typically lower than for R&E users"
+                    }
+                  ]
+                }
+              ],
+              "rows": [
+                {
+                  "value": "collaboration",
+                  "text": "Connection to your network for collaboration with R&E users"
+                },
+                {
+                  "value": "services",
+                  "text": "Connection to your network for supplying services for R&E"
+                },
+                {
+                  "value": "peering",
+                  "text": "Direct peering (e.g. direct peering or cloud peering)"
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "remote_campuses",
+              "title": "Do you provide connectivity to any remote campuses in other countries?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "remote_campuses_specifics",
+              "visibleIf": "{remote_campuses} = 'Yes'",
+              "indent": 1,
+              "title": "Please specify:",
+              "columns": [
+                {
+                  "name": "country",
+                  "title": "Which Country",
+                  "cellType": "text",
+                  "isRequired": true
+                },
+                {
+                  "name": "connected",
+                  "title": "Connected to local R&E network",
+                  "cellType": "radiogroup",
+                  "choices": [
+                    "Yes",
+                    "No"
+                  ]
+                }
+              ],
+              "rowCount": 0,
+              "maxRowCount": 50
+            },
+            {
+              "type": "comment",
+              "name": "connected_users_comments",
+              "title": "Comments regarding this section:"
+            }
+          ],
+          "title": "CONNECTED USERS - COMMERCIAL"
+        }
+      ],
+      "title": "Connected Users"
+    },
+    {
+      "name": "network",
+      "elements": [
+        {
+          "type": "panel",
+          "name": "connectivity",
+          "elements": [
+            {
+              "type": "radiogroup",
+              "name": "dark_fibre_lease",
+              "title": "Does your NREN have an IRU or lease of dark fibre?",
+              "description": "An Indefeasible Right of Use (IRU) is essentially a long-term lease of a portion of the capacity of a cable. Please do not include fibre that you have installed and own yourself. This is covered in a later question.",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "dark_fibre_lease_kilometers_inside_country",
+              "visibleIf": "{dark_fibre_lease} = 'Yes'",
+              "indent": 1,
+              "title": "Please state the number of kilometres of such fibre in your country:",
+              "description": "Please include only the fibre inside your country for this answer. The distance is the number of km’s of your fibre pairs or if you are using bidirectional traffic on a single fibre please treat this as a fibre pair.",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                },
+                {
+                  "type": "regex",
+                  "text": "Please round to a whole number",
+                  "regex": "^[0-9]*$"
+                }
+              ]
+            },
+            {
+              "type": "text",
+              "name": "dark_fibre_lease_kilometers_outside_country",
+              "visibleIf": "{dark_fibre_lease} = 'Yes'",
+              "indent": 1,
+              "title": "Please state the number of km of such fibre that is outside your country:",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                },
+                {
+                  "type": "regex",
+                  "text": "Please round to a whole number",
+                  "regex": "^[0-9]*$"
+                }
+              ]
+            },
+            {
+              "type": "text",
+              "name": "dark_fibre_lease_duration",
+              "visibleIf": "{dark_fibre_lease} = 'Yes'",
+              "indent": 1,
+              "title": "What is the average duration, in years, of your IRU?",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "dark_fibre_nren",
+              "title": "Has your NREN physically laid any dark fibre cables in your network?",
+              "description": "Please include only cables that you laid yourself. If this cable was installed and is owned by a third party, this is included in a previous question.",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "dark_fibre_nren_kilometers_inside_country",
+              "visibleIf": "{dark_fibre_nren} = 'Yes'",
+              "indent": 1,
+              "title": "Please state the number of km of such fibre in your network:",
+              "description": "Please include only the fibre inside your country for this answer. The distance is the number of km’s of your fibre pairs, or If you are using bi-directional traffic on a single fibre please treat this as a fibre pair.",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                },
+                {
+                  "type": "regex",
+                  "text": "Please round to a whole number",
+                  "regex": "^[0-9]*$"
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "fibre_light",
+              "title": "How do you light your fibre network:",
+              "choices": [
+                {
+                  "value": "nren_owns_and_operates",
+                  "text": "NREN owns and operates equipment"
+                },
+                {
+                  "value": "nren_owns_outsourced_operation",
+                  "text": "NREN owns equipment and operation is outsourced"
+                },
+                {
+                  "value": "outsourced_ownership_and_operation",
+                  "text": "Ownership and management are out-sourced (turn-key model)"
+                }
+              ],
+              "showOtherItem": true,
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "network_map_urls",
+              "title": "Please provide a network map for layers 1, 2 and 3 of your network:",
+              "columns": [
+                {
+                  "name": "network_map_url",
+                  "title": "Url:",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "expression",
+                      "text": "Please provide a single valid website url including http:// or https://",
+                      "expression": "validateWebsiteUrl({row.network_map_url})"
+                    }
+                  ],
+                  "inputType": "url"
+                }
+              ],
+              "rowCount": 1,
+              "maxRowCount": 50
+            }
+          ],
+          "title": "Connectivity"
+        },
+        {
+          "type": "panel",
+          "name": "performance",
+          "elements": [
+            {
+              "type": "checkbox",
+              "name": "monitoring_tools",
+              "title": "Which tools do you offer your client institutions for monitoring or troubleshooting the network?",
+              "choices": [
+                {
+                  "value": "looking_glass",
+                  "text": "Looking Glass"
+                },
+                {
+                  "value": "status_dashboard",
+                  "text": "Network or Services Status Dashboard"
+                },
+                {
+                  "value": "historical_traffic_volumes",
+                  "text": "Historical traffic volume information"
+                },
+                {
+                  "value": "netflow_analysis",
+                  "text": "Netflow analysis tool"
+                }
+              ],
+              "showOtherItem": true
+            },
+            {
+              "type": "text",
+              "name": "netflow_vendors",
+              "title": "If you process NetFlow, please, indicate the system name and vendor:"
+            },
+            {
+              "type": "radiogroup",
+              "name": "passive_monitoring",
+              "title": "Do you passively monitor international traffic?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "radiogroup",
+              "name": "passive_monitoring_tech",
+              "visibleIf": "{passive_monitoring} = 'Yes'",
+              "indent": 1,
+              "title": "Do you use:",
+              "choices": [
+                {
+                  "value": "span_ports",
+                  "text": "SPAN ports"
+                },
+                {
+                  "value": "taps",
+                  "text": "Passive optical TAPS"
+                },
+                {
+                  "value": "both",
+                  "text": "Both"
+                }
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "radiogroup",
+              "name": "traffic_statistics",
+              "title": "Do you have traffic statistics on your website?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "traffic_statistics_urls",
+              "visibleIf": "{traffic_statistics} = 'Yes'",
+              "indent": 1,
+              "title": "Please give the URL(s):",
+              "columns": [
+                {
+                  "name": "traffic_statistics_url",
+                  "title": "Url:",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "expression",
+                      "text": "Please provide a single valid website url including http:// or https://",
+                      "expression": "validateWebsiteUrl({row.traffic_statistics_url})"
+                    }
+                  ],
+                  "inputType": "url"
+                }
+              ],
+              "rowCount": 1,
+              "maxRowCount": 50
+            },
+            {
+              "type": "checkbox",
+              "name": "siem_soc_vendor",
+              "title": "If you use a SIEM/SOC system, please indicate the name of the vendor you use here:",
+              "choices": [
+                "Splunk",
+                "IBM Qradar",
+                "Exabeam",
+                "LogRythm",
+                "Securonix"
+              ],
+              "showOtherItem": true
+            },
+            {
+              "type": "checkbox",
+              "name": "certificate_service",
+              "title": "Which certificate service do you use?",
+              "choices": [
+                "TCS",
+                "Digicert",
+                {
+                  "value": "Sectigo",
+                  "text": "Sectigo (outside of TCS)"
+                },
+                "GlobalSign",
+                "GeoDaddy",
+                "GeoTrust",
+                "Entrust Datacard"
+              ],
+              "showOtherItem": true
+            },
+            {
+              "type": "radiogroup",
+              "name": "network_weather",
+              "title": "Do you have an online weather map of your network?",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "network_weather_url",
+              "visibleIf": "{network_weather} = 'Yes'",
+              "indent": 1,
+              "title": "Please give the URL:",
+              "validators": [
+                {
+                  "type": "expression",
+                  "text": "Please provide a single valid website url including http:// or https://",
+                  "expression": "validateWebsiteUrl({network_weather_url})"
+                }
+              ],
+              "inputType": "url"
+            },
+            {
+              "type": "radiogroup",
+              "name": "pert_team",
+              "title": "Do you run a PERT team?",
+              "choices": [
+                "Yes",
+                "No",
+                "Planned"
+              ],
+              "showClearButton": true
+            }
+          ],
+          "title": "PERFORMANCE MONITORING AND MANAGEMENT"
+        },
+        {
+          "type": "panel",
+          "name": "alienwave",
+          "elements": [
+            {
+              "type": "radiogroup",
+              "name": "alienwave_services",
+              "title": "Does your NREN make use of alien wavelength/lightpath services provided by third parties?",
+              "description": "This does not include alien waves used internally inside your network e.g. coloured optics on routers as they are covered in a later question.",
+              "choices": [
+                "Yes",
+                "No",
+                "Planned"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "alienwave_services_number",
+              "visibleIf": "{alienwave_services} = 'yes'",
+              "indent": 1,
+              "title": "Please state the number of individual alien wavelength services:",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                },
+                {
+                  "type": "regex",
+                  "text": "Please round to a whole number",
+                  "regex": "^[0-9]*$"
+                }
+              ]
+            },
+            {
+              "type": "radiogroup",
+              "name": "alienwave_internal",
+              "title": "Are you using alien waves internally in your network?",
+              "description": "This includes for example alien waves used between two equipment vendors e.g. coloured optics on routers carried over DWDM equipment.",
+              "choices": [
+                "Yes",
+                "No"
+              ],
+              "showClearButton": true
+            }
+          ],
+          "title": "Alienwave",
+          "description": "Pure optical connectivity services provided by the NREN without a known framing, such as foreign, alien wavelength."
+        },
+        {
+          "type": "panel",
+          "name": "capacity",
+          "elements": [
+            {
+              "type": "text",
+              "name": "max_capacity",
+              "title": "What is the capacity (in Gbit/s) of the largest link in your network used for internet traffic (either shared or dedicated)?",
+              "description": "Please provide the sum of aggregated links, but don't include backup capacity.",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                }
+              ]
+            },
+            {
+              "type": "text",
+              "name": "typical_capacity",
+              "title": "What is the current typical core usable backbone IP capacity of your network in Gbit/s?",
+              "description": "Note this refers to circuit capacity not traffic e.g. 2 x 10GE LAG aggregated links.",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                }
+              ]
+            },
+            {
+              "type": "matrixdynamic",
+              "name": "external_connections",
+              "title": "Please provide a list of the operational external IP connections (usable links excluding backup links): ",
+              "description": "This should include links to your regional backbone (GÉANT, APAN, RedCLARA etc, to other research locations, to the commercial Internet, peerings to Internet exchanges, cross-border dark fibre links and any other links you may have. Note that we are interested in the capacity for production purposes, not in any additional links that may be there for the purpose of giving resilience. Some of your capacity to your regional backbone may be used for transiting to intercontinental services; please include these too. Cross-border fibre links means those links that have been commissioned or established by the NREN from a point on the network that is near the border to another point near the border on the network of a neighbouring NREN, for example.",
+              "columns": [
+                {
+                  "name": "link_name",
+                  "title": "Link name",
+                  "cellType": "text"
+                },
+                {
+                  "name": "capacity",
+                  "title": "Capacity (Gbit/s):",
+                  "cellType": "text",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                },
+                {
+                  "name": "from_organization",
+                  "title": "The link is from (organisation):",
+                  "cellType": "text"
+                },
+                {
+                  "name": "to_organization",
+                  "title": "To (organisation):",
+                  "cellType": "text"
+                },
+                {
+                  "name": "interconnection_method",
+                  "title": "Interconnection method:",
+                  "cellType": "dropdown",
+                  "choices": [
+                    {
+                      "value": "internet_exchange",
+                      "text": "Internet exchange points"
+                    },
+                    {
+                      "value": "open_exchange",
+                      "text": "Open Exchange points"
+                    },
+                    {
+                      "value": "direct",
+                      "text": "Directly connected R&E peers"
+                    },
+                    {
+                      "value": "geant",
+                      "text": "GEANT"
+                    },
+                    {
+                      "value": "other",
+                      "text": "Other"
+                    }
+                  ]
+                }
+              ],
+              "rowCount": 1,
+              "maxRowCount": 50
+            },
+            {
+              "type": "text",
+              "name": "non_r_and_e_peers",
+              "title": "Please state how many non-R&E networks you are peering with:",
+              "description": "This should include all direct IP-peerings to commercial networks e.g. Google.",
+              "validators": [
+                {
+                  "type": "numeric",
+                  "minValue": 0
+                },
+                {
+                  "type": "regex",
+                  "text": "Please round to a whole number",
+                  "regex": "^[0-9]*$"
+                }
+              ]
+            },
+            {
+              "type": "multipletext",
+              "name": "traffic_estimate",
+              "title": "Please supply an estimate of the total amount of traffic in Terabyte from January to December ({previousyear}) for the following: ",
+              "items": [
+                {
+                  "name": "from_customers",
+                  "title": "Traffic from NREN customers (sources that are part of the remit of the NREN’s domain)",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                },
+                {
+                  "name": "to_customers",
+                  "title": "Traffic to NREN customers (sources that are part of the remit of the NREN’s domain)",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                },
+                {
+                  "name": "from_external",
+                  "title": "Traffic from external networks (sources that are outside the NREN’s domain, such as, GÉANT, General/Commercial Internet, Internet exchanges, peerings, other NRENs etc)",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                },
+                {
+                  "name": "to_external",
+                  "title": "Traffic to external networks (sources that are outside the NREN’s domain, such as, GÉANT, General/Commercial Internet, Internet exchanges, peerings, other NRENs etc)",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0
+                    }
+                  ]
+                }
+              ]
+            },
+            {
+              "type": "multipletext",
+              "name": "commodity_vs_r_e",
+              "title": "What is the ratio of commodity vs R&E traffic in your network?",
+              "validators": [
+                {
+                  "type": "expression",
+                  "text": "The percentages should add up to 100",
+                  "expression": "(sum({commodity_vs_r_e.r_e}, {commodity_vs_r_e.commodity}) = 100) or ({commodity_vs_r_e} empty)"
+                }
+              ],
+              "items": [
+                {
+                  "name": "r_e",
+                  "title": "R&E percentage",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                },
+                {
+                  "name": "commodity",
+                  "title": "Commodity percentage",
+                  "validators": [
+                    {
+                      "type": "numeric",
+                      "minValue": 0,
+                      "maxValue": 100
+                    }
+                  ]
+                }
+              ]
+            }
+          ],
+          "title": "CAPACITY"
+        },
+        {
+          "type": "panel",
+          "name": "sdn",
+          "elements": [
+            {
+              "type": "radiogroup",
+              "name": "operational_process_automation",
+              "title": "Are you automating your operational processes?",
+              "choices": [
+                "Yes",
+                "No",
+                "Planned"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "text",
+              "name": "operational_process_automation_tools",
+              "visibleIf": "{operational_process_automation} = 'yes'",
+              "indent": 1,
+              "title": "Please specify which processes and the name/s of the automation software and tools you use for it:"
+            },
+            {
+              "type": "radiogroup",
+              "name": "nfv",
+              "title": "Do you use any kind of NFV?",
+              "choices": [
+                "Yes",
+                "No",
+                "Planned"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "checkbox",
+              "name": "nfv_types",
+              "visibleIf": "{nfv} = 'yes' or {nfv} = 'planned'",
+              "indent": 1,
+              "title": "What kind of NFV do/will you use:",
+              "choices": [
+                {
+                  "value": "routers",
+                  "text": "Routers/switches"
+                },
+                {
+                  "value": "firewalls",
+                  "text": "Firewalls"
+                },
+                {
+                  "value": "load_balancers",
+                  "text": "Load balancers"
+                },
+                {
+                  "value": "vpn_concentrators",
+                  "text": "VPN Concentrator Services"
+                }
+              ],
+              "showOtherItem": true
+            },
+            {
+              "type": "radiogroup",
+              "name": "network_automation",
+              "title": "Do you use automation on your network?",
+              "choices": [
+                "Yes",
+                "No",
+                "Planned"
+              ],
+              "showClearButton": true
+            },
+            {
+              "type": "checkbox",
+              "name": "network_automation_tasks",
+              "visibleIf": "{network_automation} = 'yes' or {network_automation} = 'planned'",
+              "indent": 1,
+              "title": "What kind of task do you use it for?",
+              "choices": [
+                {
+                  "value": "provisioning",
+                  "text": "Device Provisioning"
+                },
+                {
+                  "value": "data_collection",
+                  "text": "Data Collection"
+                },
+                {
+                  "value": "config_management",
+                  "text": "Configuration Management"
+                },
+                {
+                  "value": "compliance",
+                  "text": "Compliance"
+                },
+                {
+                  "value": "reporting",
+                  "text": "Reporting"
+                },
+                {
+                  "value": "troubleshooting",
+                  "text": "Troubleshooting"
+                }
+              ]
+            }
+          ],
+          "title": "SOFTWARE-DEFINED NETWORKING (SDN) AND NETWORK FUNCTION VIRTUALISATION (NFV)"
+        },
+        {
+          "type": "comment",
+          "name": "network_comments",
+          "title": "Comments regarding this section:"
+        }
+      ],
+      "title": "Network"
+    },
+    {
+      "name": "services",
+      "elements": [
+        {
+          "type": "html",
+          "name": "services_hover_explanation",
+          "html": "Descriptions of the individual services are shown if you hover over the service name."
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_network",
+          "state": "collapsed",
+          "title": "Network services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "connectivity",
+              "text": "IP Connectivity",
+              "customDescription": "Basic IP connectivity services inc R&E and commodity internet"
+            },
+            {
+              "value": "home-vpn",
+              "text": "Remote access VPN server",
+              "customDescription": "Remote access and site-to-site VPN"
+            },
+            {
+              "value": "ipv6",
+              "text": "IPv6",
+              "customDescription": "The new version of the internet protocol (IP) that will eventually replace IPv4"
+            },
+            {
+              "value": "lambda",
+              "text": "Optical wavelength",
+              "customDescription": "Layer 1 optical channel for provision of dedicated capacity to demanding users"
+            },
+            {
+              "value": "managed-router",
+              "text": "Managed router service",
+              "customDescription": "Remote router support for institutions"
+            },
+            {
+              "value": "multicast",
+              "text": "Multicast",
+              "customDescription": "Extension to the IP protocol which allows individual packets to be sent to multiple hosts on the internet"
+            },
+            {
+              "value": "netflow",
+              "text": "Netflow tool",
+              "customDescription": "Network protocol of collecting IP traffic and monitoring network traffic"
+            },
+            {
+              "value": "user-monitoring",
+              "text": "Network troubleshooting",
+              "customDescription": "Enables users at connected institutions to monitor Internet services in real time"
+            },
+            {
+              "value": "network-monitoring",
+              "text": "Network monitoring",
+              "customDescription": "Network Information System that shows the current and past performance of the network"
+            },
+            {
+              "value": "open-lightpath-exchange",
+              "text": "Open Lightpath Exchange",
+              "customDescription": "Provision of an Open Lightpath exchange for users to connect to other users"
+            },
+            {
+              "value": "pert",
+              "text": "PERT",
+              "customDescription": "Team supporting resolution of end-to-end performance problems for networked applications"
+            },
+            {
+              "value": "point-to-point-circuit-vpn",
+              "text": "Virtual circuit/VPN",
+              "customDescription": "Virtual point to point circuits or VPNs delivered as a service to users "
+            },
+            {
+              "value": "quality-of-service",
+              "text": "Quality of Service",
+              "customDescription": "Preferential service to specific applications or classes of applications"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_isp",
+          "state": "collapsed",
+          "title": "ISP services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "domain-registration",
+              "text": "Domain name registration",
+              "customDescription": "Adminstration/registration of top and second level domain names"
+            },
+            {
+              "value": "ip-address-allocation",
+              "text": "IP address allocation",
+              "customDescription": "Allocating addresses for users according to the RIPE policies"
+            },
+            {
+              "value": "ix-operation",
+              "text": "National IX operation",
+              "customDescription": "Operating an IX with national importance"
+            },
+            {
+              "value": "nameserver",
+              "text": "Nameserver services",
+              "customDescription": "Operation of nameservers and maintenance of DNS information on behalf of users"
+            },
+            {
+              "value": "timeserver-ntp",
+              "text": "NTP service",
+              "customDescription": "Allows the synchronization of computer clocks over the internet"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_security",
+          "state": "collapsed",
+          "title": "Security services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "anti-spam",
+              "text": "Anti-spam solution",
+              "customDescription": "Anti-Spam solutions for detecting and eliminating viruses and spam mails"
+            },
+            {
+              "value": "csirt",
+              "text": "CERT/CSIRT",
+              "customDescription": "A single point of contact for users to deal with computer security incidents and prevention"
+            },
+            {
+              "value": "ddos-prevention",
+              "text": "DDoS mitigation",
+              "customDescription": "Tools and techniques for mitigating Distributed Denial of Service attacks"
+            },
+            {
+              "value": "firewall-on-demand",
+              "text": "Firewall-on-demand",
+              "customDescription": "Provision of a dynamic firewall services to mitigate against DDoS attacks"
+            },
+            {
+              "value": "intrusion",
+              "text": "Intrusion detection",
+              "customDescription": "System for detecting and preventing Intrusions (IDS/IPS)"
+            },
+            {
+              "value": "pgp-key",
+              "text": "PGP key server",
+              "customDescription": "Operation of PGP key server"
+            },
+            {
+              "value": "security-audit",
+              "text": "Security auditing",
+              "customDescription": "Carrying out vulnerability assessments and security reviews of user systems and resources on their behalf"
+            },
+            {
+              "value": "vulnerability-testing",
+              "text": "Vulnerability scanning",
+              "customDescription": "Vulnerability service that allows users to scan their own IP networks fo security holes"
+            },
+            {
+              "value": "web-filtering",
+              "text": "Web filtering",
+              "customDescription": "Centralised web content filtering service for protection against access to inappropriate content"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_identity",
+          "state": "collapsed",
+          "title": "Identity services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "aai",
+              "text": "Hosted campus AAI",
+              "customDescription": "Hosting of an Identity Provider service on behalf of connected Institutions to authenticate users"
+            },
+            {
+              "value": "eduroam-wifi",
+              "text": "Eduroam",
+              "customDescription": "Inter-WLAN service to facilitate easy and secure Internet access for roaming educationals users"
+            },
+            {
+              "value": "interfederation",
+              "text": "Interfederation",
+              "customDescription": "Participation in an interfederation (i.e. eduGAIN, KALMAR)"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_hosting",
+          "state": "collapsed",
+          "title": "Storage & hosting services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "cloud-service-end-user",
+              "text": "Cloud storage (end user)",
+              "customDescription": "Browser-based virtual storage service for individuals"
+            },
+            {
+              "value": "content-delivery-hosting",
+              "text": "Content delivery hosting",
+              "customDescription": "Hosting of contenct delivery servers, e.g. Akamai"
+            },
+            {
+              "value": "disaster-recovery",
+              "text": "Disaster recovery",
+              "customDescription": "Off site backup services"
+            },
+            {
+              "value": "dns-server",
+              "text": "DNS hosting",
+              "customDescription": "Hosting of primary and secondary DNS servers"
+            },
+            {
+              "value": "email-services",
+              "text": "Email server hosting",
+              "customDescription": "NREN hosted email servers."
+            },
+            {
+              "value": "filesender",
+              "text": "Filesender",
+              "customDescription": "Web-based application that allows authenticated userds to securely and easily send arbitrarily large files"
+            },
+            {
+              "value": "saas",
+              "text": "SaaS",
+              "customDescription": "Software as a service e.g. Google Apps for Education"
+            },
+            {
+              "value": "storage-co-location",
+              "text": "Housing/co-location",
+              "customDescription": "Hosting of user equipment in a managed data centre"
+            },
+            {
+              "value": "virtual-machines-iaas",
+              "text": "Virtual machines/IaaS",
+              "customDescription": "Access to virtual computing resources"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_multimedia",
+          "state": "collapsed",
+          "title": "Multimedia services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "internet-radio-tv",
+              "text": "TV/radio streaming",
+              "customDescription": "Internet and radio streaming services"
+            },
+            {
+              "value": "videoconferencing",
+              "text": "Event recording/streaming",
+              "customDescription": "Provision of equipment and/or software to support event streaming/recording"
+            },
+            {
+              "value": "video-portal",
+              "text": "Provision of content portal",
+              "customDescription": "Multi-media content portal"
+            },
+            {
+              "value": "web-conferencing",
+              "text": "Web/desktop conferencing",
+              "customDescription": "Video conferencing service to desktops and hand-held devices using software"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_collaboration",
+          "state": "collapsed",
+          "title": "Collaboration services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "e-portfolio",
+              "text": "E-portfolio service",
+              "customDescription": "Functions to create user professional and career portfolios"
+            },
+            {
+              "value": "identifier-reg",
+              "text": "Identifier Registry",
+              "customDescription": "Registering of unique and automatically-processable identifiers in the form of text or numeric strings"
+            },
+            {
+              "value": "journal-library-access",
+              "text": "Journal access",
+              "customDescription": "Access to academic journals"
+            },
+            {
+              "value": "mailing-lists",
+              "text": "Mailing lists",
+              "customDescription": "Service for operation of electronic discussion lists"
+            },
+            {
+              "value": "project-collaboration-toolkit",
+              "text": "Project collaboration",
+              "customDescription": "Packaged services or virtual project groups e.g. mailing lists, storage, web meetings, wiki."
+            },
+            {
+              "value": "scheduling-tool",
+              "text": "Scheduling tool",
+              "customDescription": "Provision of tools to users for scheduling appointments or classes"
+            },
+            {
+              "value": "survey-tool",
+              "text": "Survey/polling tool",
+              "customDescription": "Provision of applications for creating surveys or polls"
+            },
+            {
+              "value": "virtual-learning-environment",
+              "text": "VLE",
+              "customDescription": "Online e-learning education system that provides virtual access to resources used in teaching"
+            },
+            {
+              "value": "voip",
+              "text": "VoIP",
+              "customDescription": "Service to deliver voice communications and multimedia sessions over Internet Protocal (IP) networks"
+            },
+            {
+              "value": "web-email-hosting",
+              "text": "Web hosting",
+              "customDescription": "Service to provide space on central web servers for users to publish their website"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "matrixdropdown",
+          "name": "services_professional",
+          "state": "collapsed",
+          "title": "Professional services",
+          "hideCheckboxLabels": true,
+          "columns": [
+            {
+              "name": "offered",
+              "title": "Service offered",
+              "cellType": "checkbox",
+              "choices": [
+                {
+                  "value": "yes",
+                  "text": "Yes"
+                }
+              ]
+            },
+            {
+              "name": "name",
+              "title": "Service name",
+              "cellType": "text",
+              "visibleIf": "{row.offered} = ['yes']"
+            },
+            {
+              "name": "description",
+              "title": "Official description",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2
+            },
+            {
+              "name": "additional_information",
+              "title": "Additional information",
+              "cellType": "comment",
+              "visibleIf": "{row.offered} = ['yes']",
+              "rows": 2,
+              "placeholder": "(e.g. software used, third party service, links, etc.)"
+            }
+          ],
+          "cellType": "checkbox",
+          "rows": [
+            {
+              "value": "consultancy",
+              "text": "Consultancy/training",
+              "customDescription": "Training and consultancy services provided by the NREN"
+            },
+            {
+              "value": "dissemination",
+              "text": "Dissemination",
+              "customDescription": "Dissemination of information to users e.g newsletters and magazines"
+            },
+            {
+              "value": "procurement",
+              "text": "Procurement/brokerage",
+              "customDescription": "Procurement services and framework agreements"
+            },
+            {
+              "value": "software-licenses",
+              "text": "Software licenses",
+              "customDescription": "Provision of software for organisational or institutional purchase"
+            },
+            {
+              "value": "user-conference",
+              "text": "User conferences",
+              "customDescription": "Hosting of regular user conferences"
+            },
+            {
+              "value": "user-portal",
+              "text": "User portals",
+              "customDescription": "User portals for service management and monitoring"
+            }
+          ],
+          "rowTitleWidth": "20%"
+        },
+        {
+          "type": "comment",
+          "name": "service_comments",
+          "title": "Comments regarding this section:"
+        }
+      ],
+      "title": "Services"
+    }
+  ],
+  "showQuestionNumbers": "onPage",
+  "checkErrorsMode": "onValueChanged"
+}
+"""
+
+year1 = 2022
+year2 = 2023
+
+
+def upgrade():
+    survey = new_survey_model.replace('\n', '')
+    op.execute(sa.text(
+        f"UPDATE survey SET survey = :new_survey ::json WHERE year IN ({year1}, {year2})"
+    ).bindparams(new_survey=survey))
+
+
+def downgrade():
+    # we dont supply a downgrade; use git to create a new upgrade with the required changes
+    pass
diff --git a/compendium_v2/static/survey-bundle.js b/compendium_v2/static/survey-bundle.js
index 996a567fa0ae41b6a2bceb454ba0596f6cf3033b..90845c3e786e9180305f0fbbffc938d84a12eb18 100644
--- a/compendium_v2/static/survey-bundle.js
+++ b/compendium_v2/static/survey-bundle.js
@@ -169,4 +169,4 @@ to {
   > * {
     pointer-events: auto;
   }
-`,Qr=({reverseOrder:e,position:n="top-center",toastOptions:r,gutter:o,children:i,containerStyle:s,containerClassName:a})=>{let{toasts:l,handlers:u}=(e=>{let{toasts:n,pausedAt:r}=((e={})=>{let[n,r]=(0,t.useState)(fr);(0,t.useEffect)((()=>(hr.push(r),()=>{let e=hr.indexOf(r);e>-1&&hr.splice(e,1)})),[n]);let o=n.toasts.map((t=>{var n,r;return{...e,...e[t.type],...t,duration:t.duration||(null==(n=e[t.type])?void 0:n.duration)||(null==e?void 0:e.duration)||mr[t.type],style:{...e.style,...null==(r=e[t.type])?void 0:r.style,...t.style}}}));return{...n,toasts:o}})(e);(0,t.useEffect)((()=>{if(r)return;let e=Date.now(),t=n.map((t=>{if(t.duration===1/0)return;let n=(t.duration||0)+t.pauseDuration-(e-t.createdAt);if(!(n<0))return setTimeout((()=>vr.dismiss(t.id)),n);t.visible&&vr.dismiss(t.id)}));return()=>{t.forEach((e=>e&&clearTimeout(e)))}}),[n,r]);let o=(0,t.useCallback)((()=>{r&&gr({type:6,time:Date.now()})}),[r]),i=(0,t.useCallback)(((e,t)=>{let{reverseOrder:r=!1,gutter:o=8,defaultPosition:i}=t||{},s=n.filter((t=>(t.position||i)===(e.position||i)&&t.height)),a=s.findIndex((t=>t.id===e.id)),l=s.filter(((e,t)=>t<a&&e.visible)).length;return s.filter((e=>e.visible)).slice(...r?[l+1]:[0,l]).reduce(((e,t)=>e+(t.height||0)+o),0)}),[n]);return{toasts:n,handlers:{updateHeight:br,startPause:Cr,endPause:o,calculateOffset:i}}})(r);return t.createElement("div",{style:{position:"fixed",zIndex:9999,top:16,left:16,right:16,bottom:16,pointerEvents:"none",...s},className:a,onMouseEnter:u.startPause,onMouseLeave:u.endPause},l.map((r=>{let s=r.position||n,a=((e,t)=>{let n=e.includes("top"),r=n?{top:0}:{bottom:0},o=e.includes("center")?{justifyContent:"center"}:e.includes("right")?{justifyContent:"flex-end"}:{};return{left:0,right:0,display:"flex",position:"absolute",transition:ur()?void 0:"all 230ms cubic-bezier(.21,1.02,.73,1)",transform:`translateY(${t*(n?1:-1)}px)`,...r,...o}})(s,u.calculateOffset(r,{reverseOrder:e,gutter:o,defaultPosition:n}));return t.createElement(Br,{id:r.id,key:r.id,onHeightUpdate:u.updateHeight,className:r.visible?Fr:"",style:a},"custom"===r.type?ar(r.message,r):i?i(r):t.createElement(Ar,{toast:r,position:s}))})))},zr=vr,Hr=n(535),Ur=n(352),Wr=function(e){return e.Unverified="unverified",e.Verified="verified",e.Edited="edited",e}({});function Jr(e,t){if(0==t.column.indexValue&&"item"in t.row){var n,r=t.row.item;void 0!==r.customDescription&&(null===(n=t.htmlElement.parentElement)||void 0===n||n.children[0].setAttribute("title",r.customDescription))}}function $r(e){var t=e[0];if(void 0===t||null==t||""==t)return!0;try{var n=new URL(t);return"http:"===n.protocol||"https:"===n.protocol}catch(e){return!1}}function Gr(e,t){t.question.hideCheckboxLabels&&(t.cssClasses.root+=" hidden-checkbox-labels")}function Kr(e,t,n){var r;n.verificationStatus.set(e.name,t);var o=document.createElement("button");o.type="button",o.className="sv-action-bar-item verification",o.innerHTML=t,t==Wr.Unverified?(o.innerHTML="No change from previous year",o.className+=" verification-required",o.onclick=function(){"display"!=n.mode&&(e.validate(),Kr(e,Wr.Verified,n))}):(o.innerHTML="Answer updated",o.className+=" verification-ok");var i='[data-name="'+e.name+'"]',s=null===(r=document.querySelector(i))||void 0===r?void 0:r.querySelector("h5"),a=null==s?void 0:s.querySelector(".verification");a?a.replaceWith(o):null==s||s.appendChild(o)}const Zr=function(e){var n=e.surveyModel,r=(0,t.useCallback)((function(e,t){var r=n.verificationStatus.get(t.question.name);r&&Kr(t.question,r,n)}),[n]),o=(0,t.useCallback)((function(e,t){n.verificationStatus.get(t.question.name)==Wr.Unverified&&Kr(t.question,Wr.Edited,n)}),[n]);return Hr.FunctionFactory.Instance.hasFunction("validateWebsiteUrl")||Hr.FunctionFactory.Instance.register("validateWebsiteUrl",$r),n.css.question.title.includes("sv-header-flex")||(n.css.question.title="sv-title sv-question__title sv-header-flex",n.css.question.titleOnError="sv-question__title--error sv-error-color-fix"),n.onAfterRenderQuestion.hasFunc(r)||n.onAfterRenderQuestion.add(r),n.onValueChanged.hasFunc(o)||n.onValueChanged.add(o),n.onUpdateQuestionCssClasses.hasFunc(Gr)||n.onUpdateQuestionCssClasses.add(Gr),n.onMatrixAfterCellRender.hasFunc(Jr)||n.onMatrixAfterCellRender.add(Jr),t.createElement(Ur.Survey,{model:n})},Yr=t.forwardRef(((e,t)=>{const[{className:n,...r},{as:o="div",bsPrefix:i,spans:s}]=function({as:e,bsPrefix:t,className:n,...r}){t=wt(t,"col");const o=xt(),i=Pt(),s=[],a=[];return o.forEach((e=>{const n=r[e];let o,l,u;delete r[e],"object"==typeof n&&null!=n?({span:o,offset:l,order:u}=n):o=n;const c=e!==i?`-${e}`:"";o&&s.push(!0===o?`${t}${c}`:`${t}${c}-${o}`),null!=u&&a.push(`order${c}-${u}`),null!=l&&a.push(`offset${c}-${l}`)})),[{...r,className:dt()(n,...s,...a)},{as:e,bsPrefix:t,spans:s}]}(e);return(0,yt.jsx)(o,{...r,ref:t,className:dt()(n,!s.length&&i)})}));Yr.displayName="Col";const Xr=Yr;function eo(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function to(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?eo(Object(n),!0).forEach((function(t){Rn(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):eo(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}const no=function(e){var n=e.surveyModel,r=e.pageNoSetter,o=st((0,t.useState)([]),2),i=o[0],s=o[1],a=function(e){return!(null===e.value||void 0===e.value||""===e.value||"checkbox"===e.getType()&&0==e.value.length||"multipletext"===e.getType()&&(1===Object.keys(e.value).length&&void 0===Object.values(e.value)[0]||0===Object.keys(e.value).length))};(0,t.useEffect)((function(){var e=function(e){if(e&&e.pages){var t=[];e.pages.forEach((function(n){var r=n.questions.filter((function(e){return e.startWithNewLine})),o=r.length,i=r.filter(a).length,s=o-i,l=i/o;t.push({completionPercentage:100*l,unansweredPercentage:s/o*100,totalPages:e.pages.length,pageTitle:n.title})})),s(t)}};n.onValueChanged.add((function(t){e(t)})),e(n)}),[n]);var l={height:"0.5rem",transition:"width 0.3s ease"};return t.createElement(Dn,{className:"survey-progress"},t.createElement(Mn,null,i.map((function(e,o){return t.createElement(Xr,{xs:12,md:!0,key:o,onClick:function(){return r(o)},style:{cursor:"pointer",margin:"0.5rem"}},t.createElement("div",null,t.createElement("span",{style:{whiteSpace:"nowrap",fontSize:"1.5rem",marginRight:"0.25rem",fontWeight:"bold",color:"#2db394"}},o+1),t.createElement("span",{style:to({whiteSpace:"nowrap"},n.currentPageNo==o&&{fontWeight:"bold"})},e.pageTitle),t.createElement("div",{style:{display:"flex",flexWrap:"wrap"}},t.createElement("div",{style:to(to({},l),{},{width:"".concat(e.completionPercentage,"%"),backgroundColor:"#262261"})}),t.createElement("div",{style:to(to({},l),{},{width:"".concat(e.unansweredPercentage,"%"),backgroundColor:"#cdcdcd"})}))))}))))},ro=function(e){var n=e.surveyModel,r=e.surveyActions,o=e.year,i=e.nren,s=e.children,a=st((0,t.useState)(0),2),l=a[0],u=a[1],c=st((0,t.useState)(!1),2),p=c[0],d=c[1],h=st((0,t.useState)(""),2),f=h[0],g=h[1],m=st((0,t.useState)(""),2),y=m[0],v=m[1],b=(0,t.useContext)(kn).user,C=(0,t.useCallback)((function(){d("edit"==n.mode),g(n.lockedBy),u(n.currentPageNo),v(n.status)}),[n]);(0,t.useEffect)((function(){C()}),[C]);var w=function(){var e=lt(ct().mark((function e(t){return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,r[t]();case 2:C();case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),x=function(e,n){return t.createElement("button",{className:"sv-btn sv-btn--navigation",onClick:function(){return w(n)}},e)},P="Save and stop editing",S="Save progress",V="Start editing",E="Complete Survey",O=function(){return t.createElement("div",{className:"survey-edit-buttons-block"},!p&&!f&&n.editAllowed&&x(V,"startEdit"),!p&&f&&f==b.name&&x("Discard any unsaved changes and release your lock","releaseLock"),p&&l===n.visiblePages.length-1&&x(E,"complete"),p&&x(P,"saveAndStopEdit"),p&&x(S,"save"))},_=parseInt(o);return t.createElement(Dn,null,t.createElement(Mn,{className:"survey-content"},t.createElement("h2",null,t.createElement("span",{className:"survey-title"},o," Compendium Survey "),t.createElement("span",{className:"survey-title-nren"}," ",i," "),t.createElement("span",null," - ",y)),t.createElement("p",{style:{marginTop:"1rem"}},"To get started, click “",V,"” to end read-only mode. This is only possible when nobody else from your NREN is currently working on the survey.",t.createElement("br",null),"Where available, the survey questions are pre-filled with answers from the previous year. The survey asks about the past year, i.e. the ",o," survey asks about data from ",_-1," (or ",_-1,"/",o," if your NRENs financial year does not match the calendar year). You can edit the prefilled answer to provide new information, or press the “no change from previous year” button.",t.createElement("br",null),"Press the “",S,"“ or “",P,"“ button to save all answers in the survey. When you reach the last section of the survey (Services), you will find a “",E,"“ button which saves all answers in the survey and lets the Compendium team know that your answers are ready to be published.",t.createElement("br",null),"As long as the survey remains open, any Compendium administrator from your NREN can add answers or amend existing ones, even after using the “",E,"“ button. Different people from your NREN can contribute to the survey if needed.",t.createElement("br",null),"Some fields require specific data, such as numerical data, valid http-addresses, and in some questions, the answer has to add up to 100%. If an answer does not fulfil the set criteria, the question will turn pink and an error message will appear. Fields can be left blank if you prefer not to answer a question.",t.createElement("br",null),"If you notice any errors after the survey was closed, please contact us for correcting those."),t.createElement("p",null,"Thank you for taking the time to fill in the ",o," Compendium Survey. Any questions or requests can be sent to ",t.createElement("a",{href:"mailto:Partner-Relations@geant.org"},t.createElement("span",null,"Partner-Relations@geant.org"))),p&&t.createElement(t.Fragment,null,t.createElement("br",null),t.createElement("b",null,"Remember to click “",P,"” before leaving the page."))),t.createElement(Mn,null,O()),t.createElement(Mn,{className:"survey-content"},!p&&t.createElement("div",{className:"survey-edit-explainer"},!f&&n.editAllowed&&t.createElement("span",null,"The survey is in read-only mode; click the “Start editing“ button to start editing the answers."),!f&&!n.editAllowed&&t.createElement("span",null,"The survey is in read-only mode and can not be edited by you."),f&&f!=b.name&&"The survey is in READONLY mode and currently being edited by: "+f+". To start editing the survey, ask them to complete their edits.",f&&f==b.name&&'The survey is in READONLY mode because you started editing in another tab, browser or device. To start editing the survey, either complete those edits or click the "Discard any unsaved changes" button.')),t.createElement(Mn,null,t.createElement(no,{surveyModel:n,pageNoSetter:function(e){u(e),n.currentPageNo=e}}),s),t.createElement(Mn,null,O()))},oo=function(e){var n=e.when,r=e.onPageExit;return function(e){let{router:n}=Qe(Be.UseBlocker),r=ze(Fe.UseBlocker),[o]=t.useState((()=>String(++Ue))),i=t.useCallback((t=>!!e()),[e]);n.getBlocker(o,i);t.useEffect((()=>()=>n.deleteBlocker(o)),[n,o]),r.blockers.get(o)}((function(){if(n()){var t=window.confirm(e.message);return t&&r(),!t}return!1})),t.createElement("div",null)};Hr.Serializer.addProperty("itemvalue","customDescription:text"),Hr.Serializer.addProperty("question","hideCheckboxLabels:boolean");const io=function(e){var n=e.loadFrom,r=st((0,t.useState)(),2),o=r[0],i=r[1],s=function(){let{matches:e}=t.useContext(_e),n=e[e.length-1];return n?n.params:{}}(),a=s.year,l=s.nren,u=st((0,t.useState)("loading survey..."),2),c=u[0],p=u[1],d=(0,t.useCallback)((function(e){return e.preventDefault(),e.returnValue=""}),[]),h=(0,t.useCallback)((function(){window.navigator.sendBeacon("/api/response/unlock/"+a+"/"+l)}),[]),f=(0,t.useCallback)((function(){window.navigator.sendBeacon("/api/response/unlock/"+a+"/"+l),removeEventListener("beforeunload",d,{capture:!0}),removeEventListener("pagehide",h)}),[]);if((0,t.useEffect)((function(){function e(){return(e=lt(ct().mark((function e(){var t,r,o,s;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch(n+a+(l?"/"+l:""));case 2:return t=e.sent,e.next=5,t.json();case 5:if(r=e.sent,t.ok){e.next=12;break}if(!("message"in r)){e.next=11;break}throw new Error(r.message);case 11:throw new Error("Request failed with status ".concat(t.status));case 12:for(s in(o=new Hr.Model(r.model)).setVariable("surveyyear",a),o.setVariable("previousyear",parseInt(a)-1),o.showNavigationButtons=!1,o.verificationStatus=new Map,r.verification_status)o.verificationStatus.set(s,r.verification_status[s]);o.data=r.data,o.clearIncorrectValues(!0),o.currentPageNo=r.page,o.mode=r.mode,o.lockedBy=r.locked_by,o.status=r.status,o.editAllowed=r.edit_allowed,i(o);case 26:case"end":return e.stop()}}),e)})))).apply(this,arguments)}(function(){return e.apply(this,arguments)})().catch((function(e){return p("Error when loading survey: "+e.message)}))}),[]),!o)return c;var g,m,y,v,b,C=function(){var e=lt(ct().mark((function e(t,n){var r,i,s;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(l){e.next=2;break}return e.abrupt("return","Saving not available in inpect/try mode");case 2:return r={lock_uuid:t.lockUUID,new_state:n,data:t.data,page:t.currentPageNo,verification_status:Object.fromEntries(t.verificationStatus)},e.prev=3,e.next=6,fetch("/api/response/save/"+a+"/"+l,{method:"POST",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(r)});case 6:return i=e.sent,e.next=9,i.json();case 9:if(s=e.sent,i.ok){e.next=12;break}return e.abrupt("return",s.message);case 12:o.mode=s.mode,o.lockedBy=s.locked_by,o.status=s.status,e.next=20;break;case 17:return e.prev=17,e.t0=e.catch(3),e.abrupt("return","Unknown Error: "+e.t0.message);case 20:case"end":return e.stop()}}),e,null,[[3,17]])})));return function(t,n){return e.apply(this,arguments)}}(),w=function(e){var t="",n=function(e,n){e.verificationStatus.get(n.name)==Wr.Unverified&&(""==t&&(t=n.name),n.error='Please verify that last years data is correct by editing the answer or pressing the "No change from previous year" button!')};o.onValidateQuestion.add(n);var r=e();return o.onValidateQuestion.remove(n),r||(zr("Validation failed!"),o.focusQuestion(t)),r},x={save:(b=lt(ct().mark((function e(){var t;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,C(o,"editing");case 2:t=e.sent,zr(t?"Failed saving survey: "+t:"Survey saved!");case 4:case"end":return e.stop()}}),e)}))),function(){return b.apply(this,arguments)}),complete:(v=lt(ct().mark((function e(){var t;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!w(o.validate.bind(o,!0,!0))){e.next=6;break}return e.next=4,C(o,"completed");case 4:(t=e.sent)?zr("Failed completing survey: "+t):(zr("Survey completed!"),removeEventListener("beforeunload",d,{capture:!0}),removeEventListener("pagehide",h));case 6:case"end":return e.stop()}}),e)}))),function(){return v.apply(this,arguments)}),saveAndStopEdit:(y=lt(ct().mark((function e(){var t;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,C(o,"readonly");case 2:(t=e.sent)?zr("Failed saving survey: "+t):(zr("Survey saved!"),removeEventListener("beforeunload",d,{capture:!0}),removeEventListener("pagehide",h));case 4:case"end":return e.stop()}}),e)}))),function(){return y.apply(this,arguments)}),startEdit:(m=lt(ct().mark((function e(){var t,n;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch("/api/response/lock/"+a+"/"+l,{method:"POST"});case 2:return t=e.sent,e.next=5,t.json();case 5:if(n=e.sent,t.ok){e.next=9;break}return zr("Failed starting edit: "+n.message),e.abrupt("return");case 9:addEventListener("pagehide",h),addEventListener("beforeunload",d,{capture:!0}),o.data=n.data,o.clearIncorrectValues(!0),o.mode=n.mode,o.lockedBy=n.locked_by,o.lockUUID=n.lock_uuid,o.status=n.status;case 17:case"end":return e.stop()}}),e)}))),function(){return m.apply(this,arguments)}),releaseLock:(g=lt(ct().mark((function e(){var t,n;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch("/api/response/unlock/"+a+"/"+l,{method:"POST"});case 2:return t=e.sent,e.next=5,t.json();case 5:if(n=e.sent,t.ok){e.next=9;break}return zr("Failed releasing lock: "+n.message),e.abrupt("return");case 9:o.mode=n.mode,o.lockedBy=n.locked_by,o.status=n.status;case 12:case"end":return e.stop()}}),e)}))),function(){return g.apply(this,arguments)}),validatePage:function(){w(o.validatePage.bind(o))&&zr("Page validation successful!")}};return t.createElement(Dn,{className:"survey-container"},t.createElement(Qr,null),t.createElement(oo,{message:"Are you sure you want to leave this page? Information you've entered may not be saved.",when:function(){return"edit"==o.mode&&!!l},onPageExit:f}),t.createElement(ro,{surveyModel:o,surveyActions:x,year:a,nren:l},t.createElement(Zr,{surveyModel:o})))},so=n.p+"9ab20ac1d835b50b2e01.svg",ao=function(){return t.createElement("div",{className:"external-page-nav-bar"},t.createElement(Dn,null,t.createElement(Mn,null,t.createElement(Xr,{xs:10},t.createElement("div",{className:"nav-wrapper"},t.createElement("nav",{className:"header-nav"},t.createElement("a",{href:"https://geant.org/"},t.createElement("img",{src:so})),t.createElement("ul",null,t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://network.geant.org/"},"NETWORK")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://geant.org/services/"},"SERVICES")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://community.geant.org/"},"COMMUNITY")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://tnc23.geant.org/"},"TNC")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://geant.org/projects/"},"PROJECTS")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://connect.geant.org/"},"CONNECT")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://impact.geant.org/"},"IMPACT")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://careers.geant.org/"},"CAREERS")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://about.geant.org/"},"ABOUT")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://connect.geant.org/community-news"},"NEWS")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://resources.geant.org/"},"RESOURCES")))))))))},lo=function(){var e,n=(0,t.useContext)(kn).user,r=je(),o=!!n.id,i=!!o&&!!n.nrens.length,s=i?n.nrens[0]:"",a=!!o&&n.permissions.admin;return t.createElement(Dn,{className:"py-5 grey-container"},t.createElement(Mn,null,t.createElement("div",{className:"center-text"},t.createElement("h1",{className:"geant-header"},"THE GÉANT COMPENDIUM OF NRENS SURVEY"),t.createElement("div",{className:"wordwrap pt-4",style:{maxWidth:"75rem"}},t.createElement("p",{style:{textAlign:"left"}},"Hello,",t.createElement("br",null),"Welcome to the GÉANT Compendium Survey. NREN Compendium administrators can login ",t.createElement("a",{href:"/login"},"here")," to complete their registration to fill in the 2023 Compendium survey. Once your registration has been confirmed you will receive an email from the Compendium administration team.",t.createElement("br",null),"If you are not sure whether you are a Compendium Administrator for your NREN, please contact your GÉANT Partner Relations relationship manager.",t.createElement("br",null),"Thank you."),t.createElement("span",null,"Current registration status:"),t.createElement("br",null),t.createElement("br",null),a?t.createElement("ul",null,t.createElement("li",null,t.createElement("span",null,"You are logged in as a Compendium Administrator")),t.createElement("li",null,t.createElement("span",null,"Click ",t.createElement(tt,{to:"/survey/admin/surveys"},"here")," to access the survey management page.")),t.createElement("li",null,t.createElement("span",null,"Click ",t.createElement(tt,{to:"/survey/admin/users"},"here")," to access the user management page."))):t.createElement("ul",null,!a&&i&&(e=(new Date).getFullYear(),r("/survey/response/".concat(e,"/").concat(s)),t.createElement(t.Fragment,null)),o?t.createElement("li",null,t.createElement("span",null,"You are logged in")):t.createElement("li",null,t.createElement("span",null,"You are not logged in")),o&&!i&&t.createElement("li",null,t.createElement("span",null,"Your access to the survey has not been approved")),o&&!i&&t.createElement("li",null,t.createElement("span",null,"Once you have been approved, you will immediately be directed to the relevant survey upon visiting this page")))))))};var uo,co=(uo=[{path:"survey/admin/surveys",element:t.createElement(_n,null)},{path:"survey/admin/users",element:t.createElement(Hn,null)},{path:"survey/admin/inspect/:year",element:t.createElement(io,{loadFrom:"/api/response/inspect/"})},{path:"survey/admin/try/:year",element:t.createElement(io,{loadFrom:"/api/response/try/"})},{path:"survey/response/:year/:nren",element:t.createElement(io,{loadFrom:"/api/response/load/"})},{path:"*",element:t.createElement(lo,null)}],function(t){let n;if(s(t.routes.length>0,"You must provide a non-empty routes array to createRouter"),t.mapRouteProperties)n=t.mapRouteProperties;else if(t.detectErrorBoundary){let e=t.detectErrorBoundary;n=t=>({hasErrorBoundary:e(t)})}else n=Z;let r,i={},l=f(t.routes,n,void 0,i),c=t.basename||"/",p=o({v7_normalizeFormMethod:!1,v7_prependBasename:!1},t.future),h=null,m=new Set,y=null,v=null,b=null,C=null!=t.hydrationData,w=g(l,t.history.location,c),x=null;if(null==w){let e=pe(404,{pathname:t.history.location.pathname}),{matches:n,route:r}=ce(l);w=n,x={[r.id]:e}}let P,S,V=!(w.some((e=>e.route.lazy))||w.some((e=>e.route.loader))&&null==t.hydrationData),E={historyAction:t.history.action,location:t.history.location,matches:w,initialized:V,navigation:U,restoreScrollPosition:null==t.hydrationData&&null,preventScrollReset:!1,revalidation:"idle",loaderData:t.hydrationData&&t.hydrationData.loaderData||{},actionData:t.hydrationData&&t.hydrationData.actionData||null,errors:t.hydrationData&&t.hydrationData.errors||x,fetchers:new Map,blockers:new Map},O=e.Pop,_=!1,R=!1,I=!1,D=[],j=[],M=new Map,q=0,L=-1,k=new Map,N=new Set,A=new Map,B=new Map,F=new Map,Q=!1;function z(e){E=o({},E,e),m.forEach((e=>e(E)))}function te(n,i){var s,a;let u,c=null!=E.actionData&&null!=E.navigation.formMethod&&ye(E.navigation.formMethod)&&"loading"===E.navigation.state&&!0!==(null==(s=n.state)?void 0:s._isRedirect);u=i.actionData?Object.keys(i.actionData).length>0?i.actionData:null:c?E.actionData:null;let p=i.loaderData?le(E.loaderData,i.loaderData,i.matches||[],i.errors):E.loaderData;for(let[e]of F)Te(e);let d=!0===_||null!=E.navigation.formMethod&&ye(E.navigation.formMethod)&&!0!==(null==(a=n.state)?void 0:a._isRedirect);r&&(l=r,r=void 0),z(o({},i,{actionData:u,loaderData:p,historyAction:O,location:n,initialized:!0,navigation:U,revalidation:"idle",restoreScrollPosition:je(n,i.matches||E.matches),preventScrollReset:d,blockers:new Map(E.blockers)})),R||O===e.Pop||(O===e.Push?t.history.push(n,n.state):O===e.Replace&&t.history.replace(n,n.state)),O=e.Pop,_=!1,R=!1,I=!1,D=[],j=[]}async function ne(s,a,u){S&&S.abort(),S=null,O=s,R=!0===(u&&u.startUninterruptedRevalidation),function(e,t){if(y&&v&&b){let n=t.map((e=>we(e,E.loaderData))),r=v(e,n)||e.key;y[r]=b()}}(E.location,E.matches),_=!0===(u&&u.preventScrollReset);let p=r||l,h=u&&u.overrideNavigation,f=g(p,a,c);if(!f){let e=pe(404,{pathname:a.pathname}),{matches:t,route:n}=ce(p);return De(),void te(a,{matches:t,loaderData:{},errors:{[n.id]:e}})}if(E.initialized&&function(e,t){return e.pathname===t.pathname&&e.search===t.search&&(""===e.hash?""!==t.hash:e.hash===t.hash||""!==t.hash)}(E.location,a)&&!(u&&u.submission&&ye(u.submission.formMethod)))return void te(a,{matches:f});S=new AbortController;let m,C,w=ie(t.history,a,S.signal,u&&u.submission);if(u&&u.pendingError)C={[ue(f).route.id]:u.pendingError};else if(u&&u.submission&&ye(u.submission.formMethod)){let t=await async function(t,r,s,a,l){let u;Ce(),z({navigation:o({state:"submitting",location:r},s)});let p=xe(a,r);if(p.route.action||p.route.lazy){if(u=await oe("action",t,p,a,i,n,c),t.signal.aborted)return{shortCircuited:!0}}else u={type:d.error,error:pe(405,{method:t.method,pathname:r.pathname,routeId:p.route.id})};if(me(u)){let e;return e=l&&null!=l.replace?l.replace:u.location===E.location.pathname+E.location.search,await se(E,u,{submission:s,replace:e}),{shortCircuited:!0}}if(ge(u)){let t=ue(a,p.route.id);return!0!==(l&&l.replace)&&(O=e.Push),{pendingActionData:{},pendingActionError:{[t.route.id]:u.error}}}if(fe(u))throw pe(400,{type:"defer-action"});return{pendingActionData:{[p.route.id]:u.data}}}(w,a,u.submission,f,{replace:u.replace});if(t.shortCircuited)return;m=t.pendingActionData,C=t.pendingActionError,h=o({state:"loading",location:a},u.submission),w=new Request(w.url,{signal:w.signal})}let{shortCircuited:x,loaderData:P,errors:V}=await async function(e,n,i,s,a,u,p,d,h){let f=s;f||(f=o({state:"loading",location:n,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},a));let g=a||u?a||u:f.formMethod&&f.formAction&&f.formData&&f.formEncType?{formMethod:f.formMethod,formAction:f.formAction,formData:f.formData,formEncType:f.formEncType}:void 0,m=r||l,[y,v]=ee(t.history,E,i,g,n,I,D,j,A,m,c,d,h);if(De((e=>!(i&&i.some((t=>t.route.id===e)))||y&&y.some((t=>t.route.id===e)))),0===y.length&&0===v.length){let e=Oe();return te(n,o({matches:i,loaderData:{},errors:h||null},d?{actionData:d}:{},e?{fetchers:new Map(E.fetchers)}:{})),{shortCircuited:!0}}if(!R){v.forEach((e=>{let t=E.fetchers.get(e.key),n={state:"loading",data:t&&t.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(e.key,n)}));let e=d||E.actionData;z(o({navigation:f},e?0===Object.keys(e).length?{actionData:null}:{actionData:e}:{},v.length>0?{fetchers:new Map(E.fetchers)}:{}))}L=++q,v.forEach((e=>{e.controller&&M.set(e.key,e.controller)}));let b=()=>v.forEach((e=>Ve(e.key)));S&&S.signal.addEventListener("abort",b);let{results:C,loaderResults:w,fetcherResults:x}=await he(E.matches,i,y,v,e);if(e.signal.aborted)return{shortCircuited:!0};S&&S.signal.removeEventListener("abort",b),v.forEach((e=>M.delete(e.key)));let P=de(C);if(P)return await se(E,P,{replace:p}),{shortCircuited:!0};let{loaderData:V,errors:O}=ae(E,i,y,w,h,v,x,B);B.forEach(((e,t)=>{e.subscribe((n=>{(n||e.done)&&B.delete(t)}))}));let _=Oe(),T=_e(L);return o({loaderData:V,errors:O},_||T||v.length>0?{fetchers:new Map(E.fetchers)}:{})}(w,a,f,h,u&&u.submission,u&&u.fetcherSubmission,u&&u.replace,m,C);x||(S=null,te(a,o({matches:f},m?{actionData:m}:{},{loaderData:P,errors:V})))}function re(e){return E.fetchers.get(e)||W}async function se(n,r,i){var a;let{submission:l,replace:p,isFetchActionRedirect:d}=void 0===i?{}:i;r.revalidate&&(I=!0);let h=u(n.location,r.location,o({_isRedirect:!0},d?{_isFetchActionRedirect:!0}:{}));if(s(h,"Expected a location on the redirect navigation"),$.test(r.location)&&G&&void 0!==(null==(a=window)?void 0:a.location)){let e=t.history.createURL(r.location),n=null==T(e.pathname,c);if(window.location.origin!==e.origin||n)return void(p?window.location.replace(r.location):window.location.assign(r.location))}S=null;let f=!0===p?e.Replace:e.Push,{formMethod:g,formAction:m,formEncType:y,formData:v}=n.navigation;!l&&g&&m&&v&&y&&(l={formMethod:g,formAction:m,formEncType:y,formData:v}),H.has(r.status)&&l&&ye(l.formMethod)?await ne(f,h,{submission:o({},l,{formAction:r.location}),preventScrollReset:_}):d?await ne(f,h,{overrideNavigation:{state:"loading",location:h,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},fetcherSubmission:l,preventScrollReset:_}):await ne(f,h,{overrideNavigation:{state:"loading",location:h,formMethod:l?l.formMethod:void 0,formAction:l?l.formAction:void 0,formEncType:l?l.formEncType:void 0,formData:l?l.formData:void 0},preventScrollReset:_})}async function he(e,r,o,s,a){let l=await Promise.all([...o.map((e=>oe("loader",a,e,r,i,n,c))),...s.map((e=>e.matches&&e.match&&e.controller?oe("loader",ie(t.history,e.path,e.controller.signal),e.match,e.matches,i,n,c):{type:d.error,error:pe(404,{pathname:e.path})}))]),u=l.slice(0,o.length),p=l.slice(o.length);return await Promise.all([ve(e,o,u,u.map((()=>a.signal)),!1,E.loaderData),ve(e,s.map((e=>e.match)),p,s.map((e=>e.controller?e.controller.signal:null)),!0)]),{results:l,loaderResults:u,fetcherResults:p}}function Ce(){I=!0,D.push(...De()),A.forEach(((e,t)=>{M.has(t)&&(j.push(t),Ve(t))}))}function Pe(e,t,n){let r=ue(E.matches,t);Se(e),z({errors:{[r.route.id]:n},fetchers:new Map(E.fetchers)})}function Se(e){M.has(e)&&Ve(e),A.delete(e),k.delete(e),N.delete(e),E.fetchers.delete(e)}function Ve(e){let t=M.get(e);s(t,"Expected fetch controller: "+e),t.abort(),M.delete(e)}function Ee(e){for(let t of e){let e={state:"idle",data:re(t).data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(t,e)}}function Oe(){let e=[],t=!1;for(let n of N){let r=E.fetchers.get(n);s(r,"Expected fetcher: "+n),"loading"===r.state&&(N.delete(n),e.push(n),t=!0)}return Ee(e),t}function _e(e){let t=[];for(let[n,r]of k)if(r<e){let e=E.fetchers.get(n);s(e,"Expected fetcher: "+n),"loading"===e.state&&(Ve(n),k.delete(n),t.push(n))}return Ee(t),t.length>0}function Te(e){E.blockers.delete(e),F.delete(e)}function Re(e,t){let n=E.blockers.get(e)||J;s("unblocked"===n.state&&"blocked"===t.state||"blocked"===n.state&&"blocked"===t.state||"blocked"===n.state&&"proceeding"===t.state||"blocked"===n.state&&"unblocked"===t.state||"proceeding"===n.state&&"unblocked"===t.state,"Invalid blocker state transition: "+n.state+" -> "+t.state),E.blockers.set(e,t),z({blockers:new Map(E.blockers)})}function Ie(e){let{currentLocation:t,nextLocation:n,historyAction:r}=e;if(0===F.size)return;F.size>1&&a(!1,"A router only supports one blocker at a time");let o=Array.from(F.entries()),[i,s]=o[o.length-1],l=E.blockers.get(i);return l&&"proceeding"===l.state?void 0:s({currentLocation:t,nextLocation:n,historyAction:r})?i:void 0}function De(e){let t=[];return B.forEach(((n,r)=>{e&&!e(r)||(n.cancel(),t.push(r),B.delete(r))})),t}function je(e,t){if(y&&v&&b){let n=t.map((e=>we(e,E.loaderData))),r=v(e,n)||e.key,o=y[r];if("number"==typeof o)return o}return null}return P={get basename(){return c},get state(){return E},get routes(){return l},initialize:function(){return h=t.history.listen((e=>{let{action:n,location:r,delta:o}=e;if(Q)return void(Q=!1);a(0===F.size||null!=o,"You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs.  This can also happen if you are using createHashRouter and the user manually changes the URL.");let i=Ie({currentLocation:E.location,nextLocation:r,historyAction:n});return i&&null!=o?(Q=!0,t.history.go(-1*o),void Re(i,{state:"blocked",location:r,proceed(){Re(i,{state:"proceeding",proceed:void 0,reset:void 0,location:r}),t.history.go(o)},reset(){Te(i),z({blockers:new Map(P.state.blockers)})}})):ne(n,r)})),E.initialized||ne(e.Pop,E.location),P},subscribe:function(e){return m.add(e),()=>m.delete(e)},enableScrollRestoration:function(e,t,n){if(y=e,b=t,v=n||(e=>e.key),!C&&E.navigation===U){C=!0;let e=je(E.location,E.matches);null!=e&&z({restoreScrollPosition:e})}return()=>{y=null,b=null,v=null}},navigate:async function n(r,i){if("number"==typeof r)return void t.history.go(r);let s=Y(E.location,E.matches,c,p.v7_prependBasename,r,null==i?void 0:i.fromRouteId,null==i?void 0:i.relative),{path:a,submission:l,error:d}=X(p.v7_normalizeFormMethod,!1,s,i),h=E.location,f=u(E.location,a,i&&i.state);f=o({},f,t.history.encodeLocation(f));let g=i&&null!=i.replace?i.replace:void 0,m=e.Push;!0===g?m=e.Replace:!1===g||null!=l&&ye(l.formMethod)&&l.formAction===E.location.pathname+E.location.search&&(m=e.Replace);let y=i&&"preventScrollReset"in i?!0===i.preventScrollReset:void 0,v=Ie({currentLocation:h,nextLocation:f,historyAction:m});if(!v)return await ne(m,f,{submission:l,pendingError:d,preventScrollReset:y,replace:i&&i.replace});Re(v,{state:"blocked",location:f,proceed(){Re(v,{state:"proceeding",proceed:void 0,reset:void 0,location:f}),n(r,i)},reset(){Te(v),z({blockers:new Map(E.blockers)})}})},fetch:function(e,a,u,d){if(K)throw new Error("router.fetch() was called during the server render, but it shouldn't be. You are likely calling a useFetcher() method in the body of your component. Try moving it to a useEffect or a callback.");M.has(e)&&Ve(e);let h=r||l,f=Y(E.location,E.matches,c,p.v7_prependBasename,u,a,null==d?void 0:d.relative),m=g(h,f,c);if(!m)return void Pe(e,a,pe(404,{pathname:f}));let{path:y,submission:v}=X(p.v7_normalizeFormMethod,!0,f,d),b=xe(m,y);_=!0===(d&&d.preventScrollReset),v&&ye(v.formMethod)?async function(e,a,u,p,d,h){if(Ce(),A.delete(e),!p.route.action&&!p.route.lazy){let t=pe(405,{method:h.formMethod,pathname:u,routeId:a});return void Pe(e,a,t)}let f=E.fetchers.get(e),m=o({state:"submitting"},h,{data:f&&f.data," _hasFetcherDoneAnything ":!0});E.fetchers.set(e,m),z({fetchers:new Map(E.fetchers)});let y=new AbortController,v=ie(t.history,u,y.signal,h);M.set(e,y);let b=await oe("action",v,p,d,i,n,c);if(v.signal.aborted)return void(M.get(e)===y&&M.delete(e));if(me(b)){M.delete(e),N.add(e);let t=o({state:"loading"},h,{data:void 0," _hasFetcherDoneAnything ":!0});return E.fetchers.set(e,t),z({fetchers:new Map(E.fetchers)}),se(E,b,{submission:h,isFetchActionRedirect:!0})}if(ge(b))return void Pe(e,a,b.error);if(fe(b))throw pe(400,{type:"defer-action"});let C=E.navigation.location||E.location,w=ie(t.history,C,y.signal),x=r||l,P="idle"!==E.navigation.state?g(x,E.navigation.location,c):E.matches;s(P,"Didn't find any matches after fetcher action");let V=++q;k.set(e,V);let _=o({state:"loading",data:b.data},h,{" _hasFetcherDoneAnything ":!0});E.fetchers.set(e,_);let[T,R]=ee(t.history,E,P,h,C,I,D,j,A,x,c,{[p.route.id]:b.data},void 0);R.filter((t=>t.key!==e)).forEach((e=>{let t=e.key,n=E.fetchers.get(t),r={state:"loading",data:n&&n.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(t,r),e.controller&&M.set(t,e.controller)})),z({fetchers:new Map(E.fetchers)});let F=()=>R.forEach((e=>Ve(e.key)));y.signal.addEventListener("abort",F);let{results:Q,loaderResults:H,fetcherResults:U}=await he(E.matches,P,T,R,w);if(y.signal.aborted)return;y.signal.removeEventListener("abort",F),k.delete(e),M.delete(e),R.forEach((e=>M.delete(e.key)));let W=de(Q);if(W)return se(E,W);let{loaderData:J,errors:$}=ae(E,E.matches,T,H,void 0,R,U,B),G={state:"idle",data:b.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(e,G);let K=_e(V);"loading"===E.navigation.state&&V>L?(s(O,"Expected pending action"),S&&S.abort(),te(E.navigation.location,{matches:P,loaderData:J,errors:$,fetchers:new Map(E.fetchers)})):(z(o({errors:$,loaderData:le(E.loaderData,J,P,$)},K?{fetchers:new Map(E.fetchers)}:{})),I=!1)}(e,a,y,b,m,v):(A.set(e,{routeId:a,path:y}),async function(e,r,a,l,u,p){let d=E.fetchers.get(e),h=o({state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},p,{data:d&&d.data," _hasFetcherDoneAnything ":!0});E.fetchers.set(e,h),z({fetchers:new Map(E.fetchers)});let f=new AbortController,g=ie(t.history,a,f.signal);M.set(e,f);let m=await oe("loader",g,l,u,i,n,c);if(fe(m)&&(m=await be(m,g.signal,!0)||m),M.get(e)===f&&M.delete(e),g.signal.aborted)return;if(me(m))return N.add(e),void await se(E,m);if(ge(m)){let t=ue(E.matches,r);return E.fetchers.delete(e),void z({fetchers:new Map(E.fetchers),errors:{[t.route.id]:m.error}})}s(!fe(m),"Unhandled fetcher deferred data");let y={state:"idle",data:m.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(e,y),z({fetchers:new Map(E.fetchers)})}(e,a,y,b,m,v))},revalidate:function(){Ce(),z({revalidation:"loading"}),"submitting"!==E.navigation.state&&("idle"!==E.navigation.state?ne(O||E.historyAction,E.navigation.location,{overrideNavigation:E.navigation}):ne(E.historyAction,E.location,{startUninterruptedRevalidation:!0}))},createHref:e=>t.history.createHref(e),encodeLocation:e=>t.history.encodeLocation(e),getFetcher:re,deleteFetcher:Se,dispose:function(){h&&h(),m.clear(),S&&S.abort(),E.fetchers.forEach(((e,t)=>Se(t))),E.blockers.forEach(((e,t)=>Te(t)))},getBlocker:function(e,t){let n=E.blockers.get(e)||J;return F.get(e)!==t&&F.set(e,t),n},deleteBlocker:Te,_internalFetchControllers:M,_internalActiveDeferreds:B,_internalSetRoutes:function(e){i={},r=f(e,n,void 0,i)}},P}({basename:void 0,future:Ke({},void 0,{v7_prependBasename:!0}),history:function(t){return void 0===t&&(t={}),function(t,n,r,a){void 0===a&&(a={});let{window:p=document.defaultView,v5Compat:d=!1}=a,h=p.history,f=e.Pop,g=null,m=y();function y(){return(h.state||{idx:null}).idx}function v(){f=e.Pop;let t=y(),n=null==t?null:t-m;m=t,g&&g({action:f,location:C.location,delta:n})}function b(e){let t="null"!==p.location.origin?p.location.origin:p.location.href,n="string"==typeof e?e:c(e);return s(t,"No window.location.(origin|href) available to create URL for href: "+n),new URL(n,t)}null==m&&(m=0,h.replaceState(o({},h.state,{idx:m}),""));let C={get action(){return f},get location(){return t(p,h)},listen(e){if(g)throw new Error("A history only accepts one active listener");return p.addEventListener(i,v),g=e,()=>{p.removeEventListener(i,v),g=null}},createHref:e=>n(p,e),createURL:b,encodeLocation(e){let t=b(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(t,n){f=e.Push;let o=u(C.location,t,n);r&&r(o,t),m=y()+1;let i=l(o,m),s=C.createHref(o);try{h.pushState(i,"",s)}catch(e){p.location.assign(s)}d&&g&&g({action:f,location:C.location,delta:1})},replace:function(t,n){f=e.Replace;let o=u(C.location,t,n);r&&r(o,t),m=y();let i=l(o,m),s=C.createHref(o);h.replaceState(i,"",s),d&&g&&g({action:f,location:C.location,delta:0})},go:e=>h.go(e)};return C}((function(e,t){let{pathname:n,search:r,hash:o}=e.location;return u("",{pathname:n,search:r,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){return"string"==typeof t?t:c(t)}),null,t)}({window:void 0}),hydrationData:function(){var e;let t=null==(e=window)?void 0:e.__staticRouterHydrationData;return t&&t.errors&&(t=Ke({},t,{errors:Ye(t.errors)})),t}(),routes:uo,mapRouteProperties:function(e){let n={hasErrorBoundary:null!=e.ErrorBoundary||null!=e.errorElement};return e.Component&&Object.assign(n,{element:t.createElement(e.Component),Component:void 0}),e.ErrorBoundary&&Object.assign(n,{errorElement:t.createElement(e.ErrorBoundary),ErrorBoundary:void 0}),n}}).initialize());const po=function(){return t.createElement("div",{className:"app"},t.createElement(Nn,null,t.createElement(ao,null),t.createElement(We,{router:co})))};var ho=document.getElementById("root");(0,r.s)(ho).render(t.createElement(t.StrictMode,null,t.createElement(po,null)))})()})();
\ No newline at end of file
+`,Qr=({reverseOrder:e,position:n="top-center",toastOptions:r,gutter:o,children:i,containerStyle:s,containerClassName:a})=>{let{toasts:l,handlers:u}=(e=>{let{toasts:n,pausedAt:r}=((e={})=>{let[n,r]=(0,t.useState)(fr);(0,t.useEffect)((()=>(hr.push(r),()=>{let e=hr.indexOf(r);e>-1&&hr.splice(e,1)})),[n]);let o=n.toasts.map((t=>{var n,r;return{...e,...e[t.type],...t,duration:t.duration||(null==(n=e[t.type])?void 0:n.duration)||(null==e?void 0:e.duration)||mr[t.type],style:{...e.style,...null==(r=e[t.type])?void 0:r.style,...t.style}}}));return{...n,toasts:o}})(e);(0,t.useEffect)((()=>{if(r)return;let e=Date.now(),t=n.map((t=>{if(t.duration===1/0)return;let n=(t.duration||0)+t.pauseDuration-(e-t.createdAt);if(!(n<0))return setTimeout((()=>vr.dismiss(t.id)),n);t.visible&&vr.dismiss(t.id)}));return()=>{t.forEach((e=>e&&clearTimeout(e)))}}),[n,r]);let o=(0,t.useCallback)((()=>{r&&gr({type:6,time:Date.now()})}),[r]),i=(0,t.useCallback)(((e,t)=>{let{reverseOrder:r=!1,gutter:o=8,defaultPosition:i}=t||{},s=n.filter((t=>(t.position||i)===(e.position||i)&&t.height)),a=s.findIndex((t=>t.id===e.id)),l=s.filter(((e,t)=>t<a&&e.visible)).length;return s.filter((e=>e.visible)).slice(...r?[l+1]:[0,l]).reduce(((e,t)=>e+(t.height||0)+o),0)}),[n]);return{toasts:n,handlers:{updateHeight:br,startPause:Cr,endPause:o,calculateOffset:i}}})(r);return t.createElement("div",{style:{position:"fixed",zIndex:9999,top:16,left:16,right:16,bottom:16,pointerEvents:"none",...s},className:a,onMouseEnter:u.startPause,onMouseLeave:u.endPause},l.map((r=>{let s=r.position||n,a=((e,t)=>{let n=e.includes("top"),r=n?{top:0}:{bottom:0},o=e.includes("center")?{justifyContent:"center"}:e.includes("right")?{justifyContent:"flex-end"}:{};return{left:0,right:0,display:"flex",position:"absolute",transition:ur()?void 0:"all 230ms cubic-bezier(.21,1.02,.73,1)",transform:`translateY(${t*(n?1:-1)}px)`,...r,...o}})(s,u.calculateOffset(r,{reverseOrder:e,gutter:o,defaultPosition:n}));return t.createElement(Br,{id:r.id,key:r.id,onHeightUpdate:u.updateHeight,className:r.visible?Fr:"",style:a},"custom"===r.type?ar(r.message,r):i?i(r):t.createElement(Ar,{toast:r,position:s}))})))},zr=vr,Hr=n(535),Ur=n(352),Wr=function(e){return e.Unverified="unverified",e.Verified="verified",e.Edited="edited",e}({});function Jr(e,t){if(0==t.column.indexValue&&"item"in t.row){var n,r=t.row.item;void 0!==r.customDescription&&(null===(n=t.htmlElement.parentElement)||void 0===n||n.children[0].setAttribute("title",r.customDescription))}}function $r(e){var t=e[0];if(void 0===t||null==t||""==t)return!0;try{var n=new URL(t);return"http:"===n.protocol||"https:"===n.protocol}catch(e){return!1}}function Gr(e,t){t.question.hideCheckboxLabels&&(t.cssClasses.root+=" hidden-checkbox-labels")}function Kr(e,t,n){var r;n.verificationStatus.set(e.name,t);var o=document.createElement("button");o.type="button",o.className="sv-action-bar-item verification",o.innerHTML=t,t==Wr.Unverified?(o.innerHTML="No change from previous year",o.className+=" verification-required",o.onclick=function(){"display"!=n.mode&&(e.validate(),Kr(e,Wr.Verified,n))}):(o.innerHTML="Answer updated",o.className+=" verification-ok");var i='[data-name="'+e.name+'"]',s=null===(r=document.querySelector(i))||void 0===r?void 0:r.querySelector("h5"),a=null==s?void 0:s.querySelector(".verification");a?a.replaceWith(o):null==s||s.appendChild(o)}const Zr=function(e){var n=e.surveyModel,r=(0,t.useCallback)((function(e,t){var r=n.verificationStatus.get(t.question.name);r&&Kr(t.question,r,n)}),[n]),o=(0,t.useCallback)((function(e,t){n.verificationStatus.get(t.question.name)==Wr.Unverified&&Kr(t.question,Wr.Edited,n)}),[n]);return Hr.FunctionFactory.Instance.hasFunction("validateWebsiteUrl")||Hr.FunctionFactory.Instance.register("validateWebsiteUrl",$r),n.css.question.title.includes("sv-header-flex")||(n.css.question.title="sv-title sv-question__title sv-header-flex",n.css.question.titleOnError="sv-question__title--error sv-error-color-fix"),n.onAfterRenderQuestion.hasFunc(r)||n.onAfterRenderQuestion.add(r),n.onValueChanged.hasFunc(o)||n.onValueChanged.add(o),n.onUpdateQuestionCssClasses.hasFunc(Gr)||n.onUpdateQuestionCssClasses.add(Gr),n.onMatrixAfterCellRender.hasFunc(Jr)||n.onMatrixAfterCellRender.add(Jr),t.createElement(Ur.Survey,{model:n})},Yr=t.forwardRef(((e,t)=>{const[{className:n,...r},{as:o="div",bsPrefix:i,spans:s}]=function({as:e,bsPrefix:t,className:n,...r}){t=wt(t,"col");const o=xt(),i=Pt(),s=[],a=[];return o.forEach((e=>{const n=r[e];let o,l,u;delete r[e],"object"==typeof n&&null!=n?({span:o,offset:l,order:u}=n):o=n;const c=e!==i?`-${e}`:"";o&&s.push(!0===o?`${t}${c}`:`${t}${c}-${o}`),null!=u&&a.push(`order${c}-${u}`),null!=l&&a.push(`offset${c}-${l}`)})),[{...r,className:dt()(n,...s,...a)},{as:e,bsPrefix:t,spans:s}]}(e);return(0,yt.jsx)(o,{...r,ref:t,className:dt()(n,!s.length&&i)})}));Yr.displayName="Col";const Xr=Yr;function eo(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function to(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?eo(Object(n),!0).forEach((function(t){Rn(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):eo(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}const no=function(e){var n=e.surveyModel,r=e.pageNoSetter,o=st((0,t.useState)([]),2),i=o[0],s=o[1],a=function(e){return!(null===e.value||void 0===e.value||""===e.value||"checkbox"===e.getType()&&0==e.value.length||"multipletext"===e.getType()&&(1===Object.keys(e.value).length&&void 0===Object.values(e.value)[0]||0===Object.keys(e.value).length))};(0,t.useEffect)((function(){var e=function(e){if(e&&e.pages){var t=[];e.pages.forEach((function(n){var r=n.questions.filter((function(e){return e.startWithNewLine})),o=r.length,i=r.filter(a).length,s=o-i,l=i/o;t.push({completionPercentage:100*l,unansweredPercentage:s/o*100,totalPages:e.pages.length,pageTitle:n.title})})),s(t)}};n.onValueChanged.add((function(t){e(t)})),e(n)}),[n]);var l={height:"0.5rem",transition:"width 0.3s ease"};return t.createElement(Dn,{className:"survey-progress"},t.createElement(Mn,null,i.map((function(e,o){return t.createElement(Xr,{xs:12,md:!0,key:o,onClick:function(){return r(o)},style:{cursor:"pointer",margin:"0.5rem"}},t.createElement("div",null,t.createElement("span",{style:{whiteSpace:"nowrap",fontSize:"1.5rem",marginRight:"0.25rem",fontWeight:"bold",color:"#2db394"}},o+1),t.createElement("span",{style:to({whiteSpace:"nowrap"},n.currentPageNo==o&&{fontWeight:"bold"})},e.pageTitle),t.createElement("div",{style:{display:"flex",flexWrap:"wrap"}},t.createElement("div",{style:to(to({},l),{},{width:"".concat(e.completionPercentage,"%"),backgroundColor:"#262261"})}),t.createElement("div",{style:to(to({},l),{},{width:"".concat(e.unansweredPercentage,"%"),backgroundColor:"#cdcdcd"})}))))}))))},ro=function(e){var n=e.surveyModel,r=e.surveyActions,o=e.year,i=e.nren,s=e.children,a=st((0,t.useState)(0),2),l=a[0],u=a[1],c=st((0,t.useState)(!1),2),p=c[0],d=c[1],h=st((0,t.useState)(""),2),f=h[0],g=h[1],m=st((0,t.useState)(""),2),y=m[0],v=m[1],b=(0,t.useContext)(kn).user,C=(0,t.useCallback)((function(){d("edit"==n.mode),g(n.lockedBy),u(n.currentPageNo),v(n.status)}),[n]);(0,t.useEffect)((function(){C()}),[C]);var w=function(){var e=lt(ct().mark((function e(t){return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,r[t]();case 2:C();case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),x=function(e,n){return t.createElement("button",{className:"sv-btn sv-btn--navigation",onClick:function(){return w(n)}},e)},P="Save and stop editing",S="Save progress",V="Start editing",E="Complete Survey",O=function(){return t.createElement("div",{className:"survey-edit-buttons-block"},!p&&!f&&n.editAllowed&&x(V,"startEdit"),!p&&f&&f==b.name&&x("Discard any unsaved changes and release your lock","releaseLock"),p&&l===n.visiblePages.length-1&&x(E,"complete"),p&&x(P,"saveAndStopEdit"),p&&x(S,"save"))},_=parseInt(o);return t.createElement(Dn,null,t.createElement(Mn,{className:"survey-content"},t.createElement("h2",null,t.createElement("span",{className:"survey-title"},o," Compendium Survey "),t.createElement("span",{className:"survey-title-nren"}," ",i," "),t.createElement("span",null," - ",y)),t.createElement("p",{style:{marginTop:"1rem"}},"To get started, click “",V,"” to end read-only mode. This is only possible when nobody else from your NREN is currently working on the survey.",t.createElement("br",null),"Where available, the survey questions are pre-filled with answers from the previous year. The survey asks about the past year, i.e. the ",o," survey asks about data from ",_-1," (or ",_-1,"/",o," if your NRENs financial year does not match the calendar year). You can edit the prefilled answer to provide new information, or press the “no change from previous year” button.",t.createElement("br",null),"Press the “",S,"“ or “",P,"“ button to save all answers in the survey. When you reach the last section of the survey (Services), you will find a “",E,"“ button which saves all answers in the survey and lets the Compendium team know that your answers are ready to be published.",t.createElement("br",null),"As long as the survey remains open, any Compendium administrator from your NREN can add answers or amend existing ones, even after using the “",E,"“ button. Different people from your NREN can contribute to the survey if needed.",t.createElement("br",null),"Some fields require specific data, such as numerical data, valid http-addresses, and in some questions, the answer has to add up to 100%. If an answer does not fulfil the set criteria, the question will turn pink and an error message will appear. Fields can be left blank if you prefer not to answer a question.",t.createElement("br",null),"If you notice any errors after the survey was closed, please contact us for correcting those."),t.createElement("p",null,"Thank you for taking the time to fill in the ",o," Compendium Survey. Any questions or requests can be sent to ",t.createElement("a",{href:"mailto:Partner-Relations@geant.org"},t.createElement("span",null,"Partner-Relations@geant.org"))),p&&t.createElement(t.Fragment,null,t.createElement("br",null),t.createElement("b",null,"Remember to click “",P,"” before leaving the page."))),t.createElement(Mn,null,O()),t.createElement(Mn,{className:"survey-content"},!p&&t.createElement("div",{className:"survey-edit-explainer"},!f&&n.editAllowed&&t.createElement("span",null,"The survey is in read-only mode; click the “Start editing“ button to start editing the answers."),!f&&!n.editAllowed&&t.createElement("span",null,"The survey is in read-only mode and can not be edited by you."),f&&f!=b.name&&"The survey is in READONLY mode and currently being edited by: "+f+". To start editing the survey, ask them to complete their edits.",f&&f==b.name&&'The survey is in READONLY mode because you started editing in another tab, browser or device. To start editing the survey, either complete those edits or click the "Discard any unsaved changes" button.')),t.createElement(Mn,null,t.createElement(no,{surveyModel:n,pageNoSetter:function(e){u(e),n.currentPageNo=e}}),s),t.createElement(Mn,null,O()))},oo=function(e){var n=e.when,r=e.onPageExit;return function(e){let{router:n}=Qe(Be.UseBlocker),r=ze(Fe.UseBlocker),[o]=t.useState((()=>String(++Ue))),i=t.useCallback((t=>!!e()),[e]);n.getBlocker(o,i);t.useEffect((()=>()=>n.deleteBlocker(o)),[n,o]),r.blockers.get(o)}((function(){if(n()){var t=window.confirm(e.message);return t&&r(),!t}return!1})),t.createElement("div",null)};Hr.Serializer.addProperty("itemvalue","customDescription:text"),Hr.Serializer.addProperty("question","hideCheckboxLabels:boolean");const io=function(e){var n=e.loadFrom,r=st((0,t.useState)(),2),o=r[0],i=r[1],s=function(){let{matches:e}=t.useContext(_e),n=e[e.length-1];return n?n.params:{}}(),a=s.year,l=s.nren,u=st((0,t.useState)("loading survey..."),2),c=u[0],p=u[1],d=(0,t.useCallback)((function(e){return e.preventDefault(),e.returnValue=""}),[]),h=(0,t.useCallback)((function(){window.navigator.sendBeacon("/api/response/unlock/"+a+"/"+l)}),[]),f=(0,t.useCallback)((function(){window.navigator.sendBeacon("/api/response/unlock/"+a+"/"+l),removeEventListener("beforeunload",d,{capture:!0}),removeEventListener("pagehide",h)}),[]);if((0,t.useEffect)((function(){function e(){return(e=lt(ct().mark((function e(){var t,r,o,s;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch(n+a+(l?"/"+l:""));case 2:return t=e.sent,e.next=5,t.json();case 5:if(r=e.sent,t.ok){e.next=12;break}if(!("message"in r)){e.next=11;break}throw new Error(r.message);case 11:throw new Error("Request failed with status ".concat(t.status));case 12:for(s in(o=new Hr.Model(r.model)).setVariable("surveyyear",a),o.setVariable("previousyear",parseInt(a)-1),o.showNavigationButtons=!1,o.requiredText="",o.verificationStatus=new Map,r.verification_status)o.verificationStatus.set(s,r.verification_status[s]);o.data=r.data,o.clearIncorrectValues(!0),o.currentPageNo=r.page,o.mode=r.mode,o.lockedBy=r.locked_by,o.status=r.status,o.editAllowed=r.edit_allowed,i(o);case 27:case"end":return e.stop()}}),e)})))).apply(this,arguments)}(function(){return e.apply(this,arguments)})().catch((function(e){return p("Error when loading survey: "+e.message)}))}),[]),!o)return c;var g,m,y,v,b,C=function(){var e=lt(ct().mark((function e(t,n){var r,i,s;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(l){e.next=2;break}return e.abrupt("return","Saving not available in inpect/try mode");case 2:return r={lock_uuid:t.lockUUID,new_state:n,data:t.data,page:t.currentPageNo,verification_status:Object.fromEntries(t.verificationStatus)},e.prev=3,e.next=6,fetch("/api/response/save/"+a+"/"+l,{method:"POST",headers:{"Content-Type":"application/json; charset=utf-8"},body:JSON.stringify(r)});case 6:return i=e.sent,e.next=9,i.json();case 9:if(s=e.sent,i.ok){e.next=12;break}return e.abrupt("return",s.message);case 12:o.mode=s.mode,o.lockedBy=s.locked_by,o.status=s.status,e.next=20;break;case 17:return e.prev=17,e.t0=e.catch(3),e.abrupt("return","Unknown Error: "+e.t0.message);case 20:case"end":return e.stop()}}),e,null,[[3,17]])})));return function(t,n){return e.apply(this,arguments)}}(),w=function(e){var t="",n=function(e,n){e.verificationStatus.get(n.name)==Wr.Unverified&&(""==t&&(t=n.name),n.error='Please verify that last years data is correct by editing the answer or pressing the "No change from previous year" button!')};o.onValidateQuestion.add(n);var r=e();return o.onValidateQuestion.remove(n),r||(zr("Validation failed!"),o.focusQuestion(t)),r},x={save:(b=lt(ct().mark((function e(){var t;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,C(o,"editing");case 2:t=e.sent,zr(t?"Failed saving survey: "+t:"Survey saved!");case 4:case"end":return e.stop()}}),e)}))),function(){return b.apply(this,arguments)}),complete:(v=lt(ct().mark((function e(){var t;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!w(o.validate.bind(o,!0,!0))){e.next=6;break}return e.next=4,C(o,"completed");case 4:(t=e.sent)?zr("Failed completing survey: "+t):(zr("Survey completed!"),removeEventListener("beforeunload",d,{capture:!0}),removeEventListener("pagehide",h));case 6:case"end":return e.stop()}}),e)}))),function(){return v.apply(this,arguments)}),saveAndStopEdit:(y=lt(ct().mark((function e(){var t;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,C(o,"readonly");case 2:(t=e.sent)?zr("Failed saving survey: "+t):(zr("Survey saved!"),removeEventListener("beforeunload",d,{capture:!0}),removeEventListener("pagehide",h));case 4:case"end":return e.stop()}}),e)}))),function(){return y.apply(this,arguments)}),startEdit:(m=lt(ct().mark((function e(){var t,n;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch("/api/response/lock/"+a+"/"+l,{method:"POST"});case 2:return t=e.sent,e.next=5,t.json();case 5:if(n=e.sent,t.ok){e.next=9;break}return zr("Failed starting edit: "+n.message),e.abrupt("return");case 9:addEventListener("pagehide",h),addEventListener("beforeunload",d,{capture:!0}),o.data=n.data,o.clearIncorrectValues(!0),o.mode=n.mode,o.lockedBy=n.locked_by,o.lockUUID=n.lock_uuid,o.status=n.status;case 17:case"end":return e.stop()}}),e)}))),function(){return m.apply(this,arguments)}),releaseLock:(g=lt(ct().mark((function e(){var t,n;return ct().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,fetch("/api/response/unlock/"+a+"/"+l,{method:"POST"});case 2:return t=e.sent,e.next=5,t.json();case 5:if(n=e.sent,t.ok){e.next=9;break}return zr("Failed releasing lock: "+n.message),e.abrupt("return");case 9:o.mode=n.mode,o.lockedBy=n.locked_by,o.status=n.status;case 12:case"end":return e.stop()}}),e)}))),function(){return g.apply(this,arguments)}),validatePage:function(){w(o.validatePage.bind(o))&&zr("Page validation successful!")}};return t.createElement(Dn,{className:"survey-container"},t.createElement(Qr,null),t.createElement(oo,{message:"Are you sure you want to leave this page? Information you've entered may not be saved.",when:function(){return"edit"==o.mode&&!!l},onPageExit:f}),t.createElement(ro,{surveyModel:o,surveyActions:x,year:a,nren:l},t.createElement(Zr,{surveyModel:o})))},so=n.p+"9ab20ac1d835b50b2e01.svg",ao=function(){return t.createElement("div",{className:"external-page-nav-bar"},t.createElement(Dn,null,t.createElement(Mn,null,t.createElement(Xr,{xs:10},t.createElement("div",{className:"nav-wrapper"},t.createElement("nav",{className:"header-nav"},t.createElement("a",{href:"https://geant.org/"},t.createElement("img",{src:so})),t.createElement("ul",null,t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://network.geant.org/"},"NETWORK")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://geant.org/services/"},"SERVICES")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://community.geant.org/"},"COMMUNITY")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://tnc23.geant.org/"},"TNC")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://geant.org/projects/"},"PROJECTS")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://connect.geant.org/"},"CONNECT")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://impact.geant.org/"},"IMPACT")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://careers.geant.org/"},"CAREERS")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://about.geant.org/"},"ABOUT")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://connect.geant.org/community-news"},"NEWS")),t.createElement("li",null,t.createElement("a",{className:"nav-link-entry",href:"https://resources.geant.org/"},"RESOURCES")))))))))},lo=function(){var e,n=(0,t.useContext)(kn).user,r=je(),o=!!n.id,i=!!o&&!!n.nrens.length,s=i?n.nrens[0]:"",a=!!o&&n.permissions.admin;return t.createElement(Dn,{className:"py-5 grey-container"},t.createElement(Mn,null,t.createElement("div",{className:"center-text"},t.createElement("h1",{className:"geant-header"},"THE GÉANT COMPENDIUM OF NRENS SURVEY"),t.createElement("div",{className:"wordwrap pt-4",style:{maxWidth:"75rem"}},t.createElement("p",{style:{textAlign:"left"}},"Hello,",t.createElement("br",null),"Welcome to the GÉANT Compendium Survey. NREN Compendium administrators can login ",t.createElement("a",{href:"/login"},"here")," to complete their registration to fill in the 2023 Compendium survey. Once your registration has been confirmed you will receive an email from the Compendium administration team.",t.createElement("br",null),"If you are not sure whether you are a Compendium Administrator for your NREN, please contact your GÉANT Partner Relations relationship manager.",t.createElement("br",null),"Thank you."),t.createElement("span",null,"Current registration status:"),t.createElement("br",null),t.createElement("br",null),a?t.createElement("ul",null,t.createElement("li",null,t.createElement("span",null,"You are logged in as a Compendium Administrator")),t.createElement("li",null,t.createElement("span",null,"Click ",t.createElement(tt,{to:"/survey/admin/surveys"},"here")," to access the survey management page.")),t.createElement("li",null,t.createElement("span",null,"Click ",t.createElement(tt,{to:"/survey/admin/users"},"here")," to access the user management page."))):t.createElement("ul",null,!a&&i&&(e=(new Date).getFullYear(),r("/survey/response/".concat(e,"/").concat(s)),t.createElement(t.Fragment,null)),o?t.createElement("li",null,t.createElement("span",null,"You are logged in")):t.createElement("li",null,t.createElement("span",null,"You are not logged in")),o&&!i&&t.createElement("li",null,t.createElement("span",null,"Your access to the survey has not been approved")),o&&!i&&t.createElement("li",null,t.createElement("span",null,"Once you have been approved, you will immediately be directed to the relevant survey upon visiting this page")))))))};var uo,co=(uo=[{path:"survey/admin/surveys",element:t.createElement(_n,null)},{path:"survey/admin/users",element:t.createElement(Hn,null)},{path:"survey/admin/inspect/:year",element:t.createElement(io,{loadFrom:"/api/response/inspect/"})},{path:"survey/admin/try/:year",element:t.createElement(io,{loadFrom:"/api/response/try/"})},{path:"survey/response/:year/:nren",element:t.createElement(io,{loadFrom:"/api/response/load/"})},{path:"*",element:t.createElement(lo,null)}],function(t){let n;if(s(t.routes.length>0,"You must provide a non-empty routes array to createRouter"),t.mapRouteProperties)n=t.mapRouteProperties;else if(t.detectErrorBoundary){let e=t.detectErrorBoundary;n=t=>({hasErrorBoundary:e(t)})}else n=Z;let r,i={},l=f(t.routes,n,void 0,i),c=t.basename||"/",p=o({v7_normalizeFormMethod:!1,v7_prependBasename:!1},t.future),h=null,m=new Set,y=null,v=null,b=null,C=null!=t.hydrationData,w=g(l,t.history.location,c),x=null;if(null==w){let e=pe(404,{pathname:t.history.location.pathname}),{matches:n,route:r}=ce(l);w=n,x={[r.id]:e}}let P,S,V=!(w.some((e=>e.route.lazy))||w.some((e=>e.route.loader))&&null==t.hydrationData),E={historyAction:t.history.action,location:t.history.location,matches:w,initialized:V,navigation:U,restoreScrollPosition:null==t.hydrationData&&null,preventScrollReset:!1,revalidation:"idle",loaderData:t.hydrationData&&t.hydrationData.loaderData||{},actionData:t.hydrationData&&t.hydrationData.actionData||null,errors:t.hydrationData&&t.hydrationData.errors||x,fetchers:new Map,blockers:new Map},O=e.Pop,_=!1,R=!1,I=!1,D=[],j=[],M=new Map,q=0,L=-1,k=new Map,N=new Set,A=new Map,B=new Map,F=new Map,Q=!1;function z(e){E=o({},E,e),m.forEach((e=>e(E)))}function te(n,i){var s,a;let u,c=null!=E.actionData&&null!=E.navigation.formMethod&&ye(E.navigation.formMethod)&&"loading"===E.navigation.state&&!0!==(null==(s=n.state)?void 0:s._isRedirect);u=i.actionData?Object.keys(i.actionData).length>0?i.actionData:null:c?E.actionData:null;let p=i.loaderData?le(E.loaderData,i.loaderData,i.matches||[],i.errors):E.loaderData;for(let[e]of F)Te(e);let d=!0===_||null!=E.navigation.formMethod&&ye(E.navigation.formMethod)&&!0!==(null==(a=n.state)?void 0:a._isRedirect);r&&(l=r,r=void 0),z(o({},i,{actionData:u,loaderData:p,historyAction:O,location:n,initialized:!0,navigation:U,revalidation:"idle",restoreScrollPosition:je(n,i.matches||E.matches),preventScrollReset:d,blockers:new Map(E.blockers)})),R||O===e.Pop||(O===e.Push?t.history.push(n,n.state):O===e.Replace&&t.history.replace(n,n.state)),O=e.Pop,_=!1,R=!1,I=!1,D=[],j=[]}async function ne(s,a,u){S&&S.abort(),S=null,O=s,R=!0===(u&&u.startUninterruptedRevalidation),function(e,t){if(y&&v&&b){let n=t.map((e=>we(e,E.loaderData))),r=v(e,n)||e.key;y[r]=b()}}(E.location,E.matches),_=!0===(u&&u.preventScrollReset);let p=r||l,h=u&&u.overrideNavigation,f=g(p,a,c);if(!f){let e=pe(404,{pathname:a.pathname}),{matches:t,route:n}=ce(p);return De(),void te(a,{matches:t,loaderData:{},errors:{[n.id]:e}})}if(E.initialized&&function(e,t){return e.pathname===t.pathname&&e.search===t.search&&(""===e.hash?""!==t.hash:e.hash===t.hash||""!==t.hash)}(E.location,a)&&!(u&&u.submission&&ye(u.submission.formMethod)))return void te(a,{matches:f});S=new AbortController;let m,C,w=ie(t.history,a,S.signal,u&&u.submission);if(u&&u.pendingError)C={[ue(f).route.id]:u.pendingError};else if(u&&u.submission&&ye(u.submission.formMethod)){let t=await async function(t,r,s,a,l){let u;Ce(),z({navigation:o({state:"submitting",location:r},s)});let p=xe(a,r);if(p.route.action||p.route.lazy){if(u=await oe("action",t,p,a,i,n,c),t.signal.aborted)return{shortCircuited:!0}}else u={type:d.error,error:pe(405,{method:t.method,pathname:r.pathname,routeId:p.route.id})};if(me(u)){let e;return e=l&&null!=l.replace?l.replace:u.location===E.location.pathname+E.location.search,await se(E,u,{submission:s,replace:e}),{shortCircuited:!0}}if(ge(u)){let t=ue(a,p.route.id);return!0!==(l&&l.replace)&&(O=e.Push),{pendingActionData:{},pendingActionError:{[t.route.id]:u.error}}}if(fe(u))throw pe(400,{type:"defer-action"});return{pendingActionData:{[p.route.id]:u.data}}}(w,a,u.submission,f,{replace:u.replace});if(t.shortCircuited)return;m=t.pendingActionData,C=t.pendingActionError,h=o({state:"loading",location:a},u.submission),w=new Request(w.url,{signal:w.signal})}let{shortCircuited:x,loaderData:P,errors:V}=await async function(e,n,i,s,a,u,p,d,h){let f=s;f||(f=o({state:"loading",location:n,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},a));let g=a||u?a||u:f.formMethod&&f.formAction&&f.formData&&f.formEncType?{formMethod:f.formMethod,formAction:f.formAction,formData:f.formData,formEncType:f.formEncType}:void 0,m=r||l,[y,v]=ee(t.history,E,i,g,n,I,D,j,A,m,c,d,h);if(De((e=>!(i&&i.some((t=>t.route.id===e)))||y&&y.some((t=>t.route.id===e)))),0===y.length&&0===v.length){let e=Oe();return te(n,o({matches:i,loaderData:{},errors:h||null},d?{actionData:d}:{},e?{fetchers:new Map(E.fetchers)}:{})),{shortCircuited:!0}}if(!R){v.forEach((e=>{let t=E.fetchers.get(e.key),n={state:"loading",data:t&&t.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(e.key,n)}));let e=d||E.actionData;z(o({navigation:f},e?0===Object.keys(e).length?{actionData:null}:{actionData:e}:{},v.length>0?{fetchers:new Map(E.fetchers)}:{}))}L=++q,v.forEach((e=>{e.controller&&M.set(e.key,e.controller)}));let b=()=>v.forEach((e=>Ve(e.key)));S&&S.signal.addEventListener("abort",b);let{results:C,loaderResults:w,fetcherResults:x}=await he(E.matches,i,y,v,e);if(e.signal.aborted)return{shortCircuited:!0};S&&S.signal.removeEventListener("abort",b),v.forEach((e=>M.delete(e.key)));let P=de(C);if(P)return await se(E,P,{replace:p}),{shortCircuited:!0};let{loaderData:V,errors:O}=ae(E,i,y,w,h,v,x,B);B.forEach(((e,t)=>{e.subscribe((n=>{(n||e.done)&&B.delete(t)}))}));let _=Oe(),T=_e(L);return o({loaderData:V,errors:O},_||T||v.length>0?{fetchers:new Map(E.fetchers)}:{})}(w,a,f,h,u&&u.submission,u&&u.fetcherSubmission,u&&u.replace,m,C);x||(S=null,te(a,o({matches:f},m?{actionData:m}:{},{loaderData:P,errors:V})))}function re(e){return E.fetchers.get(e)||W}async function se(n,r,i){var a;let{submission:l,replace:p,isFetchActionRedirect:d}=void 0===i?{}:i;r.revalidate&&(I=!0);let h=u(n.location,r.location,o({_isRedirect:!0},d?{_isFetchActionRedirect:!0}:{}));if(s(h,"Expected a location on the redirect navigation"),$.test(r.location)&&G&&void 0!==(null==(a=window)?void 0:a.location)){let e=t.history.createURL(r.location),n=null==T(e.pathname,c);if(window.location.origin!==e.origin||n)return void(p?window.location.replace(r.location):window.location.assign(r.location))}S=null;let f=!0===p?e.Replace:e.Push,{formMethod:g,formAction:m,formEncType:y,formData:v}=n.navigation;!l&&g&&m&&v&&y&&(l={formMethod:g,formAction:m,formEncType:y,formData:v}),H.has(r.status)&&l&&ye(l.formMethod)?await ne(f,h,{submission:o({},l,{formAction:r.location}),preventScrollReset:_}):d?await ne(f,h,{overrideNavigation:{state:"loading",location:h,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},fetcherSubmission:l,preventScrollReset:_}):await ne(f,h,{overrideNavigation:{state:"loading",location:h,formMethod:l?l.formMethod:void 0,formAction:l?l.formAction:void 0,formEncType:l?l.formEncType:void 0,formData:l?l.formData:void 0},preventScrollReset:_})}async function he(e,r,o,s,a){let l=await Promise.all([...o.map((e=>oe("loader",a,e,r,i,n,c))),...s.map((e=>e.matches&&e.match&&e.controller?oe("loader",ie(t.history,e.path,e.controller.signal),e.match,e.matches,i,n,c):{type:d.error,error:pe(404,{pathname:e.path})}))]),u=l.slice(0,o.length),p=l.slice(o.length);return await Promise.all([ve(e,o,u,u.map((()=>a.signal)),!1,E.loaderData),ve(e,s.map((e=>e.match)),p,s.map((e=>e.controller?e.controller.signal:null)),!0)]),{results:l,loaderResults:u,fetcherResults:p}}function Ce(){I=!0,D.push(...De()),A.forEach(((e,t)=>{M.has(t)&&(j.push(t),Ve(t))}))}function Pe(e,t,n){let r=ue(E.matches,t);Se(e),z({errors:{[r.route.id]:n},fetchers:new Map(E.fetchers)})}function Se(e){M.has(e)&&Ve(e),A.delete(e),k.delete(e),N.delete(e),E.fetchers.delete(e)}function Ve(e){let t=M.get(e);s(t,"Expected fetch controller: "+e),t.abort(),M.delete(e)}function Ee(e){for(let t of e){let e={state:"idle",data:re(t).data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(t,e)}}function Oe(){let e=[],t=!1;for(let n of N){let r=E.fetchers.get(n);s(r,"Expected fetcher: "+n),"loading"===r.state&&(N.delete(n),e.push(n),t=!0)}return Ee(e),t}function _e(e){let t=[];for(let[n,r]of k)if(r<e){let e=E.fetchers.get(n);s(e,"Expected fetcher: "+n),"loading"===e.state&&(Ve(n),k.delete(n),t.push(n))}return Ee(t),t.length>0}function Te(e){E.blockers.delete(e),F.delete(e)}function Re(e,t){let n=E.blockers.get(e)||J;s("unblocked"===n.state&&"blocked"===t.state||"blocked"===n.state&&"blocked"===t.state||"blocked"===n.state&&"proceeding"===t.state||"blocked"===n.state&&"unblocked"===t.state||"proceeding"===n.state&&"unblocked"===t.state,"Invalid blocker state transition: "+n.state+" -> "+t.state),E.blockers.set(e,t),z({blockers:new Map(E.blockers)})}function Ie(e){let{currentLocation:t,nextLocation:n,historyAction:r}=e;if(0===F.size)return;F.size>1&&a(!1,"A router only supports one blocker at a time");let o=Array.from(F.entries()),[i,s]=o[o.length-1],l=E.blockers.get(i);return l&&"proceeding"===l.state?void 0:s({currentLocation:t,nextLocation:n,historyAction:r})?i:void 0}function De(e){let t=[];return B.forEach(((n,r)=>{e&&!e(r)||(n.cancel(),t.push(r),B.delete(r))})),t}function je(e,t){if(y&&v&&b){let n=t.map((e=>we(e,E.loaderData))),r=v(e,n)||e.key,o=y[r];if("number"==typeof o)return o}return null}return P={get basename(){return c},get state(){return E},get routes(){return l},initialize:function(){return h=t.history.listen((e=>{let{action:n,location:r,delta:o}=e;if(Q)return void(Q=!1);a(0===F.size||null!=o,"You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs.  This can also happen if you are using createHashRouter and the user manually changes the URL.");let i=Ie({currentLocation:E.location,nextLocation:r,historyAction:n});return i&&null!=o?(Q=!0,t.history.go(-1*o),void Re(i,{state:"blocked",location:r,proceed(){Re(i,{state:"proceeding",proceed:void 0,reset:void 0,location:r}),t.history.go(o)},reset(){Te(i),z({blockers:new Map(P.state.blockers)})}})):ne(n,r)})),E.initialized||ne(e.Pop,E.location),P},subscribe:function(e){return m.add(e),()=>m.delete(e)},enableScrollRestoration:function(e,t,n){if(y=e,b=t,v=n||(e=>e.key),!C&&E.navigation===U){C=!0;let e=je(E.location,E.matches);null!=e&&z({restoreScrollPosition:e})}return()=>{y=null,b=null,v=null}},navigate:async function n(r,i){if("number"==typeof r)return void t.history.go(r);let s=Y(E.location,E.matches,c,p.v7_prependBasename,r,null==i?void 0:i.fromRouteId,null==i?void 0:i.relative),{path:a,submission:l,error:d}=X(p.v7_normalizeFormMethod,!1,s,i),h=E.location,f=u(E.location,a,i&&i.state);f=o({},f,t.history.encodeLocation(f));let g=i&&null!=i.replace?i.replace:void 0,m=e.Push;!0===g?m=e.Replace:!1===g||null!=l&&ye(l.formMethod)&&l.formAction===E.location.pathname+E.location.search&&(m=e.Replace);let y=i&&"preventScrollReset"in i?!0===i.preventScrollReset:void 0,v=Ie({currentLocation:h,nextLocation:f,historyAction:m});if(!v)return await ne(m,f,{submission:l,pendingError:d,preventScrollReset:y,replace:i&&i.replace});Re(v,{state:"blocked",location:f,proceed(){Re(v,{state:"proceeding",proceed:void 0,reset:void 0,location:f}),n(r,i)},reset(){Te(v),z({blockers:new Map(E.blockers)})}})},fetch:function(e,a,u,d){if(K)throw new Error("router.fetch() was called during the server render, but it shouldn't be. You are likely calling a useFetcher() method in the body of your component. Try moving it to a useEffect or a callback.");M.has(e)&&Ve(e);let h=r||l,f=Y(E.location,E.matches,c,p.v7_prependBasename,u,a,null==d?void 0:d.relative),m=g(h,f,c);if(!m)return void Pe(e,a,pe(404,{pathname:f}));let{path:y,submission:v}=X(p.v7_normalizeFormMethod,!0,f,d),b=xe(m,y);_=!0===(d&&d.preventScrollReset),v&&ye(v.formMethod)?async function(e,a,u,p,d,h){if(Ce(),A.delete(e),!p.route.action&&!p.route.lazy){let t=pe(405,{method:h.formMethod,pathname:u,routeId:a});return void Pe(e,a,t)}let f=E.fetchers.get(e),m=o({state:"submitting"},h,{data:f&&f.data," _hasFetcherDoneAnything ":!0});E.fetchers.set(e,m),z({fetchers:new Map(E.fetchers)});let y=new AbortController,v=ie(t.history,u,y.signal,h);M.set(e,y);let b=await oe("action",v,p,d,i,n,c);if(v.signal.aborted)return void(M.get(e)===y&&M.delete(e));if(me(b)){M.delete(e),N.add(e);let t=o({state:"loading"},h,{data:void 0," _hasFetcherDoneAnything ":!0});return E.fetchers.set(e,t),z({fetchers:new Map(E.fetchers)}),se(E,b,{submission:h,isFetchActionRedirect:!0})}if(ge(b))return void Pe(e,a,b.error);if(fe(b))throw pe(400,{type:"defer-action"});let C=E.navigation.location||E.location,w=ie(t.history,C,y.signal),x=r||l,P="idle"!==E.navigation.state?g(x,E.navigation.location,c):E.matches;s(P,"Didn't find any matches after fetcher action");let V=++q;k.set(e,V);let _=o({state:"loading",data:b.data},h,{" _hasFetcherDoneAnything ":!0});E.fetchers.set(e,_);let[T,R]=ee(t.history,E,P,h,C,I,D,j,A,x,c,{[p.route.id]:b.data},void 0);R.filter((t=>t.key!==e)).forEach((e=>{let t=e.key,n=E.fetchers.get(t),r={state:"loading",data:n&&n.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(t,r),e.controller&&M.set(t,e.controller)})),z({fetchers:new Map(E.fetchers)});let F=()=>R.forEach((e=>Ve(e.key)));y.signal.addEventListener("abort",F);let{results:Q,loaderResults:H,fetcherResults:U}=await he(E.matches,P,T,R,w);if(y.signal.aborted)return;y.signal.removeEventListener("abort",F),k.delete(e),M.delete(e),R.forEach((e=>M.delete(e.key)));let W=de(Q);if(W)return se(E,W);let{loaderData:J,errors:$}=ae(E,E.matches,T,H,void 0,R,U,B),G={state:"idle",data:b.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(e,G);let K=_e(V);"loading"===E.navigation.state&&V>L?(s(O,"Expected pending action"),S&&S.abort(),te(E.navigation.location,{matches:P,loaderData:J,errors:$,fetchers:new Map(E.fetchers)})):(z(o({errors:$,loaderData:le(E.loaderData,J,P,$)},K?{fetchers:new Map(E.fetchers)}:{})),I=!1)}(e,a,y,b,m,v):(A.set(e,{routeId:a,path:y}),async function(e,r,a,l,u,p){let d=E.fetchers.get(e),h=o({state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},p,{data:d&&d.data," _hasFetcherDoneAnything ":!0});E.fetchers.set(e,h),z({fetchers:new Map(E.fetchers)});let f=new AbortController,g=ie(t.history,a,f.signal);M.set(e,f);let m=await oe("loader",g,l,u,i,n,c);if(fe(m)&&(m=await be(m,g.signal,!0)||m),M.get(e)===f&&M.delete(e),g.signal.aborted)return;if(me(m))return N.add(e),void await se(E,m);if(ge(m)){let t=ue(E.matches,r);return E.fetchers.delete(e),void z({fetchers:new Map(E.fetchers),errors:{[t.route.id]:m.error}})}s(!fe(m),"Unhandled fetcher deferred data");let y={state:"idle",data:m.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};E.fetchers.set(e,y),z({fetchers:new Map(E.fetchers)})}(e,a,y,b,m,v))},revalidate:function(){Ce(),z({revalidation:"loading"}),"submitting"!==E.navigation.state&&("idle"!==E.navigation.state?ne(O||E.historyAction,E.navigation.location,{overrideNavigation:E.navigation}):ne(E.historyAction,E.location,{startUninterruptedRevalidation:!0}))},createHref:e=>t.history.createHref(e),encodeLocation:e=>t.history.encodeLocation(e),getFetcher:re,deleteFetcher:Se,dispose:function(){h&&h(),m.clear(),S&&S.abort(),E.fetchers.forEach(((e,t)=>Se(t))),E.blockers.forEach(((e,t)=>Te(t)))},getBlocker:function(e,t){let n=E.blockers.get(e)||J;return F.get(e)!==t&&F.set(e,t),n},deleteBlocker:Te,_internalFetchControllers:M,_internalActiveDeferreds:B,_internalSetRoutes:function(e){i={},r=f(e,n,void 0,i)}},P}({basename:void 0,future:Ke({},void 0,{v7_prependBasename:!0}),history:function(t){return void 0===t&&(t={}),function(t,n,r,a){void 0===a&&(a={});let{window:p=document.defaultView,v5Compat:d=!1}=a,h=p.history,f=e.Pop,g=null,m=y();function y(){return(h.state||{idx:null}).idx}function v(){f=e.Pop;let t=y(),n=null==t?null:t-m;m=t,g&&g({action:f,location:C.location,delta:n})}function b(e){let t="null"!==p.location.origin?p.location.origin:p.location.href,n="string"==typeof e?e:c(e);return s(t,"No window.location.(origin|href) available to create URL for href: "+n),new URL(n,t)}null==m&&(m=0,h.replaceState(o({},h.state,{idx:m}),""));let C={get action(){return f},get location(){return t(p,h)},listen(e){if(g)throw new Error("A history only accepts one active listener");return p.addEventListener(i,v),g=e,()=>{p.removeEventListener(i,v),g=null}},createHref:e=>n(p,e),createURL:b,encodeLocation(e){let t=b(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(t,n){f=e.Push;let o=u(C.location,t,n);r&&r(o,t),m=y()+1;let i=l(o,m),s=C.createHref(o);try{h.pushState(i,"",s)}catch(e){p.location.assign(s)}d&&g&&g({action:f,location:C.location,delta:1})},replace:function(t,n){f=e.Replace;let o=u(C.location,t,n);r&&r(o,t),m=y();let i=l(o,m),s=C.createHref(o);h.replaceState(i,"",s),d&&g&&g({action:f,location:C.location,delta:0})},go:e=>h.go(e)};return C}((function(e,t){let{pathname:n,search:r,hash:o}=e.location;return u("",{pathname:n,search:r,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){return"string"==typeof t?t:c(t)}),null,t)}({window:void 0}),hydrationData:function(){var e;let t=null==(e=window)?void 0:e.__staticRouterHydrationData;return t&&t.errors&&(t=Ke({},t,{errors:Ye(t.errors)})),t}(),routes:uo,mapRouteProperties:function(e){let n={hasErrorBoundary:null!=e.ErrorBoundary||null!=e.errorElement};return e.Component&&Object.assign(n,{element:t.createElement(e.Component),Component:void 0}),e.ErrorBoundary&&Object.assign(n,{errorElement:t.createElement(e.ErrorBoundary),ErrorBoundary:void 0}),n}}).initialize());const po=function(){return t.createElement("div",{className:"app"},t.createElement(Nn,null,t.createElement(ao,null),t.createElement(We,{router:co})))};var ho=document.getElementById("root");(0,r.s)(ho).render(t.createElement(t.StrictMode,null,t.createElement(po,null)))})()})();
\ No newline at end of file
diff --git a/survey-frontend/src/SurveyContainerComponent.tsx b/survey-frontend/src/SurveyContainerComponent.tsx
index fdf88423874aecbf723cce3356ad1192fc168e23..17076fe859431bcd39286ae5546bc7d42e9acf5b 100644
--- a/survey-frontend/src/SurveyContainerComponent.tsx
+++ b/survey-frontend/src/SurveyContainerComponent.tsx
@@ -53,6 +53,7 @@ function SurveyContainerComponent({ loadFrom }) {
             survey.setVariable('previousyear', parseInt(year!) - 1);
 
             survey.showNavigationButtons = false;
+            survey.requiredText = '';
 
             survey.verificationStatus = new Map<string, VerificationStatus>();
             for (const questionName in json["verification_status"]) {