diff --git a/.github/workflows/infra-develop.yml b/.github/workflows/infra-develop.yml
index a0044340f7..03f7e00054 100644
--- a/.github/workflows/infra-develop.yml
+++ b/.github/workflows/infra-develop.yml
@@ -5,7 +5,7 @@ on:
- develop
jobs:
- trigger-develop-build:
+ trigger-old-develop-build:
environment: Development
name: Call Azure Pipeline
runs-on: ubuntu-latest
@@ -16,3 +16,15 @@ jobs:
azure-devops-project-url: https://dev.azure.com/${{ secrets.AZURE_ORGANIZATION_NAME }}/${{ secrets.AZURE_PROJECT_NAME }}
azure-pipeline-name: ${{ secrets.AZURE_PIPELINE_NAME }}
azure-devops-token: ${{ secrets.AZURE_DEVOPS_TOKEN }}
+ trigger-develop-build:
+ environment: Development
+ name: Call Azure Pipeline
+ runs-on: ubuntu-latest
+ steps:
+ - name: Azure Pipelines Action
+ uses: Azure/pipelines@v1
+ with:
+ azure-devops-project-url: https://dev.azure.com/${{ secrets.VWS_AZURE_ORGANIZATION_NAME }}/${{ secrets.VWS_AZURE_PROJECT_NAME }}
+ azure-pipeline-name: ${{ secrets.VWS_AZURE_PIPELINE_NAME_DEV }}
+ azure-devops-token: ${{ secrets.VWS_AZURE_DEVOPS_TOKEN }}
+
diff --git a/.github/workflows/infra.yml b/.github/workflows/infra.yml
index a8b826d880..7f4935c8cf 100644
--- a/.github/workflows/infra.yml
+++ b/.github/workflows/infra.yml
@@ -6,7 +6,7 @@ on:
workflow_dispatch:
jobs:
- build:
+ old-build:
name: Call Azure Pipeline
runs-on: ubuntu-latest
steps:
@@ -16,3 +16,13 @@ jobs:
azure-devops-project-url: https://dev.azure.com/${{ secrets.AZURE_ORGANIZATION_NAME }}/${{ secrets.AZURE_PROJECT_NAME }}
azure-pipeline-name: ${{ secrets.AZURE_PIPELINE_NAME }}
azure-devops-token: ${{ secrets.AZURE_DEVOPS_TOKEN }}
+ build:
+ name: Call Azure Pipeline
+ runs-on: ubuntu-latest
+ steps:
+ - name: Azure Pipelines Action
+ uses: Azure/pipelines@v1
+ with:
+ azure-devops-project-url: https://dev.azure.com/${{ secrets.VWS_AZURE_ORGANIZATION_NAME }}/${{ secrets.VWS_AZURE_PROJECT_NAME }}
+ azure-pipeline-name: ${{ secrets.VWS_AZURE_PIPELINE_NAME_PROD }}
+ azure-devops-token: ${{ secrets.VWS_AZURE_DEVOPS_TOKEN }}
diff --git a/README.md b/README.md
index 39b128dc21..201cb17690 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,14 @@ noting:
When a component and sub-components share some
local types they are often put in a separate `types.ts` file to avoid
circular dependencies.
+- We leverage interfaces to define component property structures rather than types. The name of the interface should follow the name of the component followed by a `Props` suffix. An example would be as below.
+
+ ```jsx
+ interface RowProps { ... }
+
+ const Row = ({ myProp }: RowProps) => { ... };
+ ```
+
- Booleans are prefixed with is/has/should etc.
- Data schema properties and locale keys for the CMS are all snake_cased. These could be
viewed as external data sources / APIs.
@@ -83,12 +91,18 @@ noting:
- We avoid using `boolean && doSomething();` inside the component's JavaScript logic, but do use it inside the component's JSX (`{boolean && ( ... )}`) to conditionally render (parts of) the component.
- We avoid unnecessary short-hand variable names like
`arr` for array or `i` for index or `acc` for a `reduce` accumulator.
+- We write Styled Components using its OOTB tagged template literal functions instead of using an additional layer of the Styled System's `css()` method. This method improves readability, makes code easier to understand and sticks to the fundamentals of CSS. This method still allows for usage of Styled System's theme definitions, yet removes a dependency on the actual package.
+- We included a `Styled`-prefix when creating Styled Components. This makes them easily distinguishable from other components. Examples would be `StyledInput` or `StyledTile`.
+- We avoid using magic numbers in code, be it logic, JSX or styles. Magic numbers are often derived from the theme defined by Styled System and resolve to properties such as spacing and font-sizes, but are unclear on its own. Instead, we import the desired property and refer to the index in that properties array. An example would be `padding: 3` (undesired) vs `padding: space[3]` (desired).
+- We do not have a hard preference or requirement for using `git rebase` or `git merge`. Developers should follow what works best for them, but it should be noted that both methods are allowed and actively used in this project.
+- We do not have a hard preference or requirement for squashing a multitude of git commits, but it can be useful to apply this when creating a pull request. This action should be used on an 'as-needed basis': if a pull request grows large due to a large amount of commits, it might improve reviewability when multiple commits are squashed. It should be noted that pull requests are squashed when merged, aside from pull requests to `master`. This is to keep a clear view of features and fixes that were merged as part of a release.
+- Continuing on the above: we should write a comprehensive commit message when squash merging a pull request. This message should be a (filtered) summary of the commits on the branch.
- We use the following branch names:
- `feature/COR-XXX-descriptive-name-of-ticket-branch` for features
- `bugfix/COR-XXX-descriptive-name-of-ticket-branch` for bug fixes
- `hotfix/COR-XXX-descriptive-name-of-ticket-branch` for hotfixes
- `task/COR-XXX-descriptive-name-of-ticket-branch` for bigger features that are best reviewed in smaller chunks
-- We use commit messages according to: https://www.conventionalcommits.org/en/v1.0.0/
+- We use commit messages according to:
- `feat(optional-scope): commit description example` for features
- `fix(optional-scope): commit description example` for fixes
- `chore(optional-scope): commit description example` for cleanups
diff --git a/packages/app/schema/gm/__index.json b/packages/app/schema/gm/__index.json
index 015b7d3f4a..f90da3e170 100644
--- a/packages/app/schema/gm/__index.json
+++ b/packages/app/schema/gm/__index.json
@@ -17,7 +17,7 @@
"vaccine_coverage_per_age_group",
"vaccine_coverage_per_age_group_archived",
"vaccine_coverage_per_age_group_archived_20220908",
- "booster_coverage"
+ "booster_coverage_archived_20220904"
],
"properties": {
"last_generated": {
@@ -62,8 +62,8 @@
"vaccine_coverage_per_age_group_archived_20220908": {
"$ref": "vaccine_coverage_per_age_group_archived_20220908.json"
},
- "booster_coverage": {
- "$ref": "booster_coverage.json"
+ "booster_coverage_archived_20220904": {
+ "$ref": "booster_coverage_archived_20220904.json"
}
},
"$defs": {
diff --git a/packages/app/schema/gm/booster_coverage.json b/packages/app/schema/gm/booster_coverage_archived_20220904.json
similarity index 89%
rename from packages/app/schema/gm/booster_coverage.json
rename to packages/app/schema/gm/booster_coverage_archived_20220904.json
index eaee06edc9..43cf6de9a7 100644
--- a/packages/app/schema/gm/booster_coverage.json
+++ b/packages/app/schema/gm/booster_coverage_archived_20220904.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
- "title": "gm_booster_coverage",
+ "title": "gm_booster_coverage_archived_20220904",
"type": "object",
"properties": {
"values": {
@@ -16,7 +16,7 @@
"additionalProperties": false,
"definitions": {
"value": {
- "title": "gm_booster_coverage_value",
+ "title": "gm_booster_coverage_archived_20220904_value",
"type": "object",
"properties": {
"age_group": {
diff --git a/packages/app/schema/gm/sewer.json b/packages/app/schema/gm/sewer.json
index 00e925cffe..02c4ae016b 100644
--- a/packages/app/schema/gm/sewer.json
+++ b/packages/app/schema/gm/sewer.json
@@ -11,7 +11,8 @@
"total_number_of_samples",
"sampled_installation_count",
"total_installation_count",
- "date_of_insertion_unix"
+ "date_of_insertion_unix",
+ "data_is_outdated"
],
"properties": {
"date_start_unix": {
@@ -34,6 +35,9 @@
},
"date_of_insertion_unix": {
"type": "integer"
+ },
+ "data_is_outdated": {
+ "type": "boolean"
}
}
}
diff --git a/packages/app/schema/gm/vaccine_coverage_per_age_group.json b/packages/app/schema/gm/vaccine_coverage_per_age_group.json
index c77865c4db..d98a04f721 100644
--- a/packages/app/schema/gm/vaccine_coverage_per_age_group.json
+++ b/packages/app/schema/gm/vaccine_coverage_per_age_group.json
@@ -18,44 +18,53 @@
"additionalProperties": false,
"type": "object",
"required": [
- "age_group_range",
- "autumn_2022_vaccinated_percentage",
- "fully_vaccinated_percentage",
- "booster_shot_percentage",
- "autumn_2022_vaccinated_percentage_label",
- "fully_vaccinated_percentage_label",
- "booster_shot_percentage_label",
- "birthyear_range",
+ "vaccination_type",
+ "birthyear_range_12_plus",
+ "birthyear_range_18_plus",
+ "birthyear_range_60_plus",
+ "vaccinated_percentage_12_plus",
+ "vaccinated_percentage_12_plus_label",
+ "vaccinated_percentage_18_plus",
+ "vaccinated_percentage_18_plus_label",
+ "vaccinated_percentage_60_plus",
+ "vaccinated_percentage_60_plus_label",
"date_of_insertion_unix",
"date_unix"
],
"properties": {
- "age_group_range": {
- "type": "string",
- "enum": ["12+", "18+", "60+"]
- },
- "autumn_2022_vaccinated_percentage": {
- "type": ["integer", "null"]
- },
- "fully_vaccinated_percentage": {
- "type": ["integer", "null"]
+ "vaccination_type": {
+ "type": "string"
},
- "booster_shot_percentage": {
- "type": ["integer", "null"]
+ "birthyear_range_12_plus": {
+ "type": "string",
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "birthyear_range": {
+ "birthyear_range_18_plus": {
"type": "string",
"pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "autumn_2022_vaccinated_percentage_label": {
+ "birthyear_range_60_plus": {
+ "type": ["string", "null"],
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
+ },
+ "vaccinated_percentage_12_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_12_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "fully_vaccinated_percentage_label": {
+ "vaccinated_percentage_18_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_18_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "booster_shot_percentage_label": {
+ "vaccinated_percentage_60_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_60_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
diff --git a/packages/app/schema/gm_collection/__index.json b/packages/app/schema/gm_collection/__index.json
index 227e4878c8..c8a2d23f05 100644
--- a/packages/app/schema/gm_collection/__index.json
+++ b/packages/app/schema/gm_collection/__index.json
@@ -57,8 +57,8 @@
},
"vaccine_coverage_per_age_group": {
"type": "array",
- "minItems": 1032,
- "maxItems": 1032,
+ "minItems": 688,
+ "maxItems": 688,
"items": {
"$ref": "vaccine_coverage_per_age_group.json"
}
diff --git a/packages/app/schema/gm_collection/sewer.json b/packages/app/schema/gm_collection/sewer.json
index 87326bccf0..7cd18a9855 100644
--- a/packages/app/schema/gm_collection/sewer.json
+++ b/packages/app/schema/gm_collection/sewer.json
@@ -9,7 +9,8 @@
"gmcode",
"average",
"total_installation_count",
- "date_of_insertion_unix"
+ "date_of_insertion_unix",
+ "data_is_outdated"
],
"properties": {
"date_start_unix": {
@@ -30,6 +31,9 @@
},
"date_of_insertion_unix": {
"type": "integer"
+ },
+ "data_is_outdated": {
+ "type": "boolean"
}
}
}
diff --git a/packages/app/schema/gm_collection/vaccine_coverage_per_age_group.json b/packages/app/schema/gm_collection/vaccine_coverage_per_age_group.json
index 8a98d9edbd..464ecf98b6 100644
--- a/packages/app/schema/gm_collection/vaccine_coverage_per_age_group.json
+++ b/packages/app/schema/gm_collection/vaccine_coverage_per_age_group.json
@@ -5,14 +5,16 @@
"additionalProperties": false,
"required": [
"gmcode",
- "age_group_range",
- "birthyear_range",
- "autumn_2022_vaccinated_percentage",
- "autumn_2022_vaccinated_percentage_label",
- "fully_vaccinated_percentage",
- "fully_vaccinated_percentage_label",
- "booster_shot_percentage",
- "booster_shot_percentage_label",
+ "vaccination_type",
+ "birthyear_range_12_plus",
+ "birthyear_range_18_plus",
+ "birthyear_range_60_plus",
+ "vaccinated_percentage_12_plus",
+ "vaccinated_percentage_12_plus_label",
+ "vaccinated_percentage_18_plus",
+ "vaccinated_percentage_18_plus_label",
+ "vaccinated_percentage_60_plus",
+ "vaccinated_percentage_60_plus_label",
"date_of_insertion_unix",
"date_unix"
],
@@ -21,32 +23,39 @@
"type": "string",
"pattern": "^GM[0-9]+$"
},
- "age_group_range": {
- "type": "string",
- "enum": ["12+", "18+", "60+"]
- },
- "autumn_2022_vaccinated_percentage": {
- "type": ["integer", "null"]
- },
- "fully_vaccinated_percentage": {
- "type": ["integer", "null"]
+ "vaccination_type": {
+ "type": "string"
},
- "booster_shot_percentage": {
- "type": ["integer", "null"]
+ "birthyear_range_12_plus": {
+ "type": "string",
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "birthyear_range": {
+ "birthyear_range_18_plus": {
"type": "string",
"pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "autumn_2022_vaccinated_percentage_label": {
+ "birthyear_range_60_plus": {
+ "type": ["string", "null"],
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
+ },
+ "vaccinated_percentage_12_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_12_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "fully_vaccinated_percentage_label": {
+ "vaccinated_percentage_18_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_18_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "booster_shot_percentage_label": {
+ "vaccinated_percentage_60_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_60_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
diff --git a/packages/app/schema/nl/__index.json b/packages/app/schema/nl/__index.json
index 5ee9f640dc..b955224bdd 100644
--- a/packages/app/schema/nl/__index.json
+++ b/packages/app/schema/nl/__index.json
@@ -5,9 +5,9 @@
"required": [
"behavior",
"behavior_annotations",
- "booster_shot_administered",
+ "booster_shot_administered_archived_20220904",
"repeating_shot_administered",
- "booster_coverage",
+ "booster_coverage_archived_20220904",
"code",
"corona_melder_app_download",
"corona_melder_app_warning",
@@ -80,14 +80,14 @@
"named_difference": {
"$ref": "__named_difference.json"
},
- "booster_shot_administered": {
- "$ref": "booster_shot_administered.json"
+ "booster_shot_administered_archived_20220904": {
+ "$ref": "booster_shot_administered_archived_20220904.json"
},
"repeating_shot_administered": {
"$ref": "repeating_shot_administered.json"
},
- "booster_coverage": {
- "$ref": "booster_coverage.json"
+ "booster_coverage_archived_20220904": {
+ "$ref": "booster_coverage_archived_20220904.json"
},
"doctor": {
"$ref": "doctor.json"
diff --git a/packages/app/schema/nl/booster_coverage.json b/packages/app/schema/nl/booster_coverage_archived_20220904.json
similarity index 88%
rename from packages/app/schema/nl/booster_coverage.json
rename to packages/app/schema/nl/booster_coverage_archived_20220904.json
index f4b5cfff2f..b4e5eed9d7 100644
--- a/packages/app/schema/nl/booster_coverage.json
+++ b/packages/app/schema/nl/booster_coverage_archived_20220904.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
- "title": "nl_booster_coverage",
+ "title": "nl_booster_coverage_archived_20220904",
"type": "object",
"properties": {
"values": {
@@ -16,7 +16,7 @@
"additionalProperties": false,
"definitions": {
"value": {
- "title": "nl_booster_coverage_value",
+ "title": "nl_booster_coverage_archived_20220904_value",
"type": "object",
"properties": {
"age_group": {
diff --git a/packages/app/schema/nl/booster_shot_administered.json b/packages/app/schema/nl/booster_shot_administered_archived_20220904.json
similarity index 88%
rename from packages/app/schema/nl/booster_shot_administered.json
rename to packages/app/schema/nl/booster_shot_administered_archived_20220904.json
index 5f6326eeea..995d274b89 100644
--- a/packages/app/schema/nl/booster_shot_administered.json
+++ b/packages/app/schema/nl/booster_shot_administered_archived_20220904.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
- "title": "nl_booster_shot_administered",
+ "title": "nl_booster_shot_administered_archived_20220904",
"type": "object",
"properties": {
"values": {
@@ -19,7 +19,7 @@
"additionalProperties": false,
"definitions": {
"value": {
- "title": "nl_booster_shot_administered_value",
+ "title": "nl_booster_shot_administered_archived_20220904_value",
"type": "object",
"properties": {
"administered_total": {
diff --git a/packages/app/schema/nl/vaccine_coverage_per_age_group.json b/packages/app/schema/nl/vaccine_coverage_per_age_group.json
index b0fd6482d5..b9d8acd305 100644
--- a/packages/app/schema/nl/vaccine_coverage_per_age_group.json
+++ b/packages/app/schema/nl/vaccine_coverage_per_age_group.json
@@ -22,10 +22,8 @@
"age_group_range",
"age_group_total",
"autumn_2022_vaccinated",
- "booster_shot",
"autumn_2022_vaccinated_percentage",
"fully_vaccinated_percentage",
- "booster_shot_percentage",
"date_of_insertion_unix",
"date_unix",
"date_of_report_unix",
@@ -59,18 +57,12 @@
"fully_vaccinated": {
"type": "integer"
},
- "booster_shot": {
- "type": ["integer", "null"]
- },
"autumn_2022_vaccinated_percentage": {
"type": ["integer", "null"]
},
"fully_vaccinated_percentage": {
"type": "number"
},
- "booster_shot_percentage": {
- "type": ["number", "null"]
- },
"date_unix": {
"type": "integer"
},
diff --git a/packages/app/schema/vr/__index.json b/packages/app/schema/vr/__index.json
index 88a856d288..026e0ed88d 100644
--- a/packages/app/schema/vr/__index.json
+++ b/packages/app/schema/vr/__index.json
@@ -27,7 +27,7 @@
"vaccine_coverage_per_age_group",
"vaccine_coverage_per_age_group_archived",
"vaccine_coverage_per_age_group_archived_20220908",
- "booster_coverage"
+ "booster_coverage_archived_20220904"
],
"additionalProperties": false,
"properties": {
@@ -106,8 +106,8 @@
"vaccine_coverage_per_age_group_archived_20220908": {
"$ref": "vaccine_coverage_per_age_group_archived_20220908.json"
},
- "booster_coverage": {
- "$ref": "booster_coverage.json"
+ "booster_coverage_archived_20220904": {
+ "$ref": "booster_coverage_archived_20220904.json"
}
},
"$defs": {
diff --git a/packages/app/schema/vr/booster_coverage.json b/packages/app/schema/vr/booster_coverage_archived_20220904.json
similarity index 89%
rename from packages/app/schema/vr/booster_coverage.json
rename to packages/app/schema/vr/booster_coverage_archived_20220904.json
index d07b6435de..565ba114c4 100644
--- a/packages/app/schema/vr/booster_coverage.json
+++ b/packages/app/schema/vr/booster_coverage_archived_20220904.json
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
- "title": "vr_booster_coverage",
+ "title": "vr_booster_coverage_archived_20220904",
"type": "object",
"properties": {
"values": {
@@ -16,7 +16,7 @@
"additionalProperties": false,
"definitions": {
"value": {
- "title": "vr_booster_coverage_value",
+ "title": "vr_booster_coverage_archived_20220904_value",
"type": "object",
"properties": {
"age_group": {
diff --git a/packages/app/schema/vr/sewer.json b/packages/app/schema/vr/sewer.json
index 55764ef52a..2b87d3e818 100644
--- a/packages/app/schema/vr/sewer.json
+++ b/packages/app/schema/vr/sewer.json
@@ -4,7 +4,7 @@
"title": "vr_sewer_value",
"type": "object",
"additionalProperties": false,
- "required": ["date_unix", "average", "date_of_insertion_unix"],
+ "required": ["date_unix", "average", "date_of_insertion_unix", "data_is_outdated"],
"properties": {
"date_unix": {
"type": "integer"
@@ -14,6 +14,9 @@
},
"date_of_insertion_unix": {
"type": "integer"
+ },
+ "data_is_outdated": {
+ "type": "boolean"
}
}
}
diff --git a/packages/app/schema/vr/vaccine_coverage_per_age_group.json b/packages/app/schema/vr/vaccine_coverage_per_age_group.json
index 05e0de9d45..1733d1c6a3 100644
--- a/packages/app/schema/vr/vaccine_coverage_per_age_group.json
+++ b/packages/app/schema/vr/vaccine_coverage_per_age_group.json
@@ -18,44 +18,53 @@
"additionalProperties": false,
"type": "object",
"required": [
- "age_group_range",
- "autumn_2022_vaccinated_percentage",
- "fully_vaccinated_percentage",
- "booster_shot_percentage",
- "autumn_2022_vaccinated_percentage_label",
- "fully_vaccinated_percentage_label",
- "booster_shot_percentage_label",
- "birthyear_range",
+ "vaccination_type",
+ "birthyear_range_12_plus",
+ "birthyear_range_18_plus",
+ "birthyear_range_60_plus",
+ "vaccinated_percentage_12_plus",
+ "vaccinated_percentage_12_plus_label",
+ "vaccinated_percentage_18_plus",
+ "vaccinated_percentage_18_plus_label",
+ "vaccinated_percentage_60_plus",
+ "vaccinated_percentage_60_plus_label",
"date_of_insertion_unix",
"date_unix"
],
"properties": {
- "age_group_range": {
- "type": "string",
- "enum": ["12+", "18+", "60+"]
- },
- "autumn_2022_vaccinated_percentage": {
- "type": ["integer", "null"]
- },
- "fully_vaccinated_percentage": {
- "type": ["integer", "null"]
+ "vaccination_type": {
+ "type": "string"
},
- "booster_shot_percentage": {
- "type": ["integer", "null"]
+ "birthyear_range_12_plus": {
+ "type": "string",
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "birthyear_range": {
+ "birthyear_range_18_plus": {
"type": "string",
"pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "autumn_2022_vaccinated_percentage_label": {
+ "birthyear_range_60_plus": {
+ "type": ["string", "null"],
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
+ },
+ "vaccinated_percentage_12_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_12_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "fully_vaccinated_percentage_label": {
+ "vaccinated_percentage_18_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_18_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "booster_shot_percentage_label": {
+ "vaccinated_percentage_60_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_60_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
diff --git a/packages/app/schema/vr_collection/__index.json b/packages/app/schema/vr_collection/__index.json
index f3e8198e6d..10416e6808 100644
--- a/packages/app/schema/vr_collection/__index.json
+++ b/packages/app/schema/vr_collection/__index.json
@@ -105,8 +105,8 @@
},
"vaccine_coverage_per_age_group": {
"type": "array",
- "minItems": 75,
- "maxItems": 75,
+ "minItems": 50,
+ "maxItems": 50,
"items": {
"$ref": "vaccine_coverage_per_age_group.json"
}
diff --git a/packages/app/schema/vr_collection/sewer.json b/packages/app/schema/vr_collection/sewer.json
index 7ea55377af..649f779eaf 100644
--- a/packages/app/schema/vr_collection/sewer.json
+++ b/packages/app/schema/vr_collection/sewer.json
@@ -3,7 +3,7 @@
"title": "vr_collection_sewer",
"type": "object",
"additionalProperties": false,
- "required": ["date_unix", "vrcode", "average", "date_of_insertion_unix"],
+ "required": ["date_unix", "vrcode", "average", "date_of_insertion_unix", "data_is_outdated"],
"properties": {
"date_unix": {
"type": "integer"
@@ -17,6 +17,9 @@
},
"date_of_insertion_unix": {
"type": "integer"
+ },
+ "data_is_outdated": {
+ "type": "boolean"
}
}
}
diff --git a/packages/app/schema/vr_collection/vaccine_coverage_per_age_group.json b/packages/app/schema/vr_collection/vaccine_coverage_per_age_group.json
index a9aaeddaa0..88915c2007 100644
--- a/packages/app/schema/vr_collection/vaccine_coverage_per_age_group.json
+++ b/packages/app/schema/vr_collection/vaccine_coverage_per_age_group.json
@@ -5,14 +5,16 @@
"additionalProperties": false,
"required": [
"vrcode",
- "age_group_range",
- "birthyear_range",
- "autumn_2022_vaccinated_percentage",
- "autumn_2022_vaccinated_percentage_label",
- "fully_vaccinated_percentage_label",
- "fully_vaccinated_percentage",
- "booster_shot_percentage",
- "booster_shot_percentage_label",
+ "vaccination_type",
+ "birthyear_range_12_plus",
+ "birthyear_range_18_plus",
+ "birthyear_range_60_plus",
+ "vaccinated_percentage_12_plus",
+ "vaccinated_percentage_12_plus_label",
+ "vaccinated_percentage_18_plus",
+ "vaccinated_percentage_18_plus_label",
+ "vaccinated_percentage_60_plus",
+ "vaccinated_percentage_60_plus_label",
"date_of_insertion_unix",
"date_unix"
],
@@ -21,32 +23,39 @@
"type": "string",
"pattern": "^VR[0-9]+$"
},
- "age_group_range": {
- "type": "string",
- "enum": ["12+", "18+", "60+"]
- },
- "autumn_2022_vaccinated_percentage": {
- "type": ["integer", "null"]
- },
- "fully_vaccinated_percentage": {
- "type": ["integer", "null"]
+ "vaccination_type": {
+ "type": "string"
},
- "booster_shot_percentage": {
- "type": ["integer", "null"]
+ "birthyear_range_12_plus": {
+ "type": "string",
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "birthyear_range": {
+ "birthyear_range_18_plus": {
"type": "string",
"pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
},
- "autumn_2022_vaccinated_percentage_label": {
+ "birthyear_range_60_plus": {
+ "type": ["string", "null"],
+ "pattern": "^[0-9]{4}-[0-9]{4}$|^-[0-9]{4}$|^[0-9]{4}-$"
+ },
+ "vaccinated_percentage_12_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_12_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "fully_vaccinated_percentage_label": {
+ "vaccinated_percentage_18_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_18_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
- "booster_shot_percentage_label": {
+ "vaccinated_percentage_60_plus": {
+ "type": ["number", "null"]
+ },
+ "vaccinated_percentage_60_plus_label": {
"type": ["string", "null"],
"pattern": "^([><][=][0-9]{1,2})$"
},
diff --git a/packages/app/src/components/choropleth-legenda.tsx b/packages/app/src/components/choropleth-legenda.tsx
index 75efeb0ce8..faeaa0b1c0 100644
--- a/packages/app/src/components/choropleth-legenda.tsx
+++ b/packages/app/src/components/choropleth-legenda.tsx
@@ -1,28 +1,26 @@
-import { ChoroplethThresholdsValue } from '@corona-dashboard/common';
+import { ChoroplethThresholdsValue, colors } from '@corona-dashboard/common';
import { css, SystemStyleObject } from '@styled-system/css';
import styled from 'styled-components';
import { ValueAnnotation } from '~/components/value-annotation';
import { useIntl } from '~/intl';
+import { space, fontSizes } from '~/style/theme';
import { replaceVariablesInText } from '~/utils';
import { useBreakpoints } from '~/utils/use-breakpoints';
import { useResizeObserver } from '~/utils/use-resize-observer';
import { Box } from './base';
import { Legend, LegendItem } from './legend';
-import { Text } from './typography';
+import { InlineText, Text } from './typography';
interface ChoroplethLegendaProps {
title: string;
thresholds: ChoroplethThresholdsValue[];
valueAnnotation?: string;
type?: 'default' | 'bar';
+ pageType?: string;
+ outdatedDataLabel?: string;
}
-export function ChoroplethLegenda({
- title,
- thresholds,
- valueAnnotation,
- type = 'bar',
-}: ChoroplethLegendaProps) {
+export function ChoroplethLegenda({ title, thresholds, valueAnnotation, type = 'bar', pageType, outdatedDataLabel }: ChoroplethLegendaProps) {
const [itemRef, itemSize] = useResizeObserver();
const [endLabelRef, endLabelSize] = useResizeObserver();
const { commonTexts, formatNumber } = useIntl();
@@ -44,13 +42,18 @@ export function ChoroplethLegenda({
);
return (
-
+
{title && {title}}
+
+ {pageType === 'sewer' && (
+
+
+
+ {outdatedDataLabel}
+
+
+ )}
+
{'bar' === type ? (
{thresholds.map(({ color, threshold, label, endLabel }, index) => {
@@ -60,20 +63,11 @@ export function ChoroplethLegenda({
const formattedTreshold = formatNumber(threshold);
return (
- -
+
-
- {isFirst ? (
- {label ?? formattedTreshold}
- ) : (
- displayLabel &&
- )}
+ {isFirst ? {label ?? formattedTreshold} : displayLabel && }
- {isLast && endLabel && (
- {endLabel}
- )}
+ {isLast && endLabel && {endLabel}}
);
})}
@@ -96,9 +90,13 @@ const List = styled.ul(
})
);
-const Item = styled.li(
+// Assigning a flex-basis based on number of items in threshold so that legend items outside of the threshold array can be displayed using the same measurement.
+const Item = styled.li<{
+ width: string;
+}>(({ width }) =>
css({
flex: 1,
+ flexBasis: width,
position: 'relative',
})
);
@@ -106,6 +104,7 @@ const Item = styled.li(
const LegendaColor = styled.div<{
first?: boolean;
last?: boolean;
+ width?: string;
color: string;
}>((x) =>
css({
@@ -113,6 +112,7 @@ const LegendaColor = styled.div<{
height: '10px',
flexGrow: 0,
flexShrink: 0,
+ flexBasis: x.width,
borderRadius: x.first ? '2px 0 0 2px' : x.last ? '0 2px 2px 0' : 0,
backgroundColor: x.color,
})
diff --git a/packages/app/src/components/choropleth-tile.tsx b/packages/app/src/components/choropleth-tile.tsx
index 3556fc5405..513c06c6b5 100644
--- a/packages/app/src/components/choropleth-tile.tsx
+++ b/packages/app/src/components/choropleth-tile.tsx
@@ -3,10 +3,7 @@ import { ChoroplethLegenda } from '~/components/choropleth-legenda';
import { DataProps } from '~/types/attributes';
import { useBreakpoints } from '~/utils/use-breakpoints';
import { Box } from './base';
-import {
- ChartRegionControls,
- RegionControlOption,
-} from './chart-region-controls';
+import { ChartRegionControls, RegionControlOption } from './chart-region-controls';
import { ErrorBoundary } from './error-boundary';
import { FullscreenChartTile } from './fullscreen-chart-tile';
import { MetadataProps } from './metadata';
@@ -20,10 +17,12 @@ type ChoroplethTileProps = DataProps & {
title: string;
thresholds: ChoroplethThresholdsValue[];
type?: 'default' | 'bar';
+ outdatedDataLabel?: string;
};
metadata?: MetadataProps;
valueAnnotation?: string;
hasPadding?: boolean;
+ pageType?: string;
} & (
| {
onChartRegionChange: (v: RegionControlOption) => void;
@@ -45,6 +44,7 @@ export function ChoroplethTile({
metadata,
valueAnnotation,
hasPadding,
+ pageType,
...dataProps
}: ChoroplethTileProps) {
const breakpoints = useBreakpoints(true);
@@ -55,40 +55,23 @@ export function ChoroplethTile({
title={legend.title}
valueAnnotation={valueAnnotation}
type={legend.type}
+ pageType={pageType}
+ outdatedDataLabel={legend.outdatedDataLabel}
/>
);
return (
-
+
{title}
- {typeof description === 'string' ? (
- {description}
- ) : (
- description
- )}
+ {typeof description === 'string' ? {description} : description}
{onChartRegionChange && chartRegion && (
-
-
+
+
)}
@@ -99,18 +82,8 @@ export function ChoroplethTile({
)}
-
-
+
+
{children}
diff --git a/packages/app/src/components/choropleth/components/canvas-choropleth-map.tsx b/packages/app/src/components/choropleth/components/canvas-choropleth-map.tsx
index 39d8778329..b6f29e0142 100644
--- a/packages/app/src/components/choropleth/components/canvas-choropleth-map.tsx
+++ b/packages/app/src/components/choropleth/components/canvas-choropleth-map.tsx
@@ -1,16 +1,7 @@
import { colors } from '@corona-dashboard/common';
import type { GeoProjection } from 'd3-geo';
import Konva from 'konva';
-import {
- memo,
- MouseEvent,
- MutableRefObject,
- RefObject,
- useCallback,
- useEffect,
- useRef,
- useState,
-} from 'react';
+import { memo, MouseEvent, MutableRefObject, RefObject, useCallback, useEffect, useRef, useState } from 'react';
import { Group, Layer, Line, Stage } from 'react-konva';
import { isDefined, isPresent } from 'ts-is-present';
import { isIOSDevice } from '~/utils/is-ios-device';
@@ -18,22 +9,12 @@ import { AccessibilityAnnotations } from '~/utils/use-accessibility-annotations'
import { useIsTouchDevice } from '~/utils/use-is-touch-device';
import { useUniqueId } from '~/utils/use-unique-id';
import type { DataOptions } from '..';
-import type {
- ChoroplethFeatures,
- ChoroplethTooltipHandlers,
- CodeProp,
- FeatureProps,
- FitExtent,
-} from '../logic';
+import type { ChoroplethFeatures, ChoroplethTooltipHandlers, CodeProp, FeatureProps, FitExtent } from '../logic';
import { useHighlightedFeature } from '../logic/use-highlighted-feature';
-import {
- ProjectedGeoInfo,
- useProjectedCoordinates,
-} from '../logic/use-projected-coordinates';
+import { ProjectedGeoInfo, useProjectedCoordinates } from '../logic/use-projected-coordinates';
import type { AnchorEventHandler } from './choropleth-map';
-Konva.pixelRatio =
- typeof window !== 'undefined' ? Math.min(window.devicePixelRatio, 2) : 1;
+Konva.pixelRatio = typeof window !== 'undefined' ? Math.min(window.devicePixelRatio, 2) : 1;
export type CanvasChoroplethMapProps = {
anchorEventHandlers: AnchorEventHandler;
@@ -58,8 +39,7 @@ export type CanvasChoroplethMapProps = {
* This is one transparent pixel encoded in a dataUrl. This is used for the image overlay on top of the canvas that
* uses the area map to detect feature mouse overs
*/
-const oneTransparentPixelImage =
- 'data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAAtJREFUGFdjYAACAAAFAAGq1chRAAAAAElFTkSuQmCC';
+const oneTransparentPixelImage = 'data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAAtJREFUGFdjYAACAAAFAAGq1chRAAAAAElFTkSuQmCC';
export const CanvasChoroplethMap = (props: CanvasChoroplethMapProps) => {
const {
@@ -85,17 +65,9 @@ export const CanvasChoroplethMap = (props: CanvasChoroplethMapProps) => {
const [hoverCode, setHoverCode] = useState();
const [isKeyboardActive, setIsKeyboardActive] = useState(false);
- const [geoInfo, geoInfoLookup] = useProjectedCoordinates(
- choroplethFeatures.hover,
- mapProjection,
- fitExtent
- );
+ const [geoInfo, geoInfoLookup] = useProjectedCoordinates(choroplethFeatures.hover, mapProjection, fitExtent);
- const [outlineGeoInfo] = useProjectedCoordinates(
- choroplethFeatures.outline,
- mapProjection,
- fitExtent
- );
+ const [outlineGeoInfo] = useProjectedCoordinates(choroplethFeatures.outline, mapProjection, fitExtent);
const highlightedFeature = useHighlightedFeature(geoInfo, dataOptions);
@@ -197,29 +169,12 @@ export const CanvasChoroplethMap = (props: CanvasChoroplethMapProps) => {
>
-
+
-
+
-
+
>
@@ -266,8 +221,7 @@ type HoveredFeatureProps = {
};
const HoveredFeature = memo((props: HoveredFeatureProps) => {
- const { hoveredRef, hover, hoverCode, featureProps, isKeyboardActive } =
- props;
+ const { hoveredRef, hover, hoverCode, featureProps, isKeyboardActive } = props;
if (!isDefined(hoverCode) || !isDefined(hover)) {
return null;
@@ -285,11 +239,7 @@ const HoveredFeature = memo((props: HoveredFeatureProps) => {
points={x.flat()}
strokeWidth={featureProps.hover.strokeWidth(hoverCode, true)}
closed
- stroke={featureProps.hover.stroke(
- hoverCode,
- true,
- isKeyboardActive
- )}
+ stroke={featureProps.hover.stroke(hoverCode, true, isKeyboardActive)}
/>
))}
@@ -392,10 +342,7 @@ type AreaMapProps = {
getLink?: (code: string) => string;
getFeatureName: (code: string) => string;
anchorEventHandlers: AnchorEventHandler;
- selectFeature: (
- code: CodeProp | undefined,
- isKeyboardAction?: boolean
- ) => void;
+ selectFeature: (code: CodeProp | undefined, isKeyboardAction?: boolean) => void;
id: string;
handleMouseOver: (event: MouseEvent) => void;
height: number;
@@ -408,24 +355,11 @@ type GeoInfoGroup = {
};
function AreaMap(props: AreaMapProps) {
- const {
- isTabInteractive,
- geoInfo,
- getLink,
- getFeatureName,
- selectFeature,
- anchorEventHandlers,
- id,
- handleMouseOver,
- height,
- width,
- } = props;
+ const { isTabInteractive, geoInfo, getLink, getFeatureName, selectFeature, anchorEventHandlers, id, handleMouseOver, height, width } = props;
- const geoInfoGroups: GeoInfoGroup[] = geoInfo.reduce(
- (geoInfoGroups, geoItem) => {
- const index = geoInfoGroups.findIndex(
- (geoInfoGroup) => geoInfoGroup.code === geoItem.code
- );
+ const geoInfoGroups: GeoInfoGroup[] = geoInfo
+ .reduce((geoInfoGroups, geoItem) => {
+ const index = geoInfoGroups.findIndex((geoInfoGroup) => geoInfoGroup.code === geoItem.code);
if (index === -1) {
geoInfoGroups.push({
code: geoItem.code,
@@ -435,18 +369,15 @@ function AreaMap(props: AreaMapProps) {
geoInfoGroups[index].coordinatesList.push(geoItem.coordinates);
}
return geoInfoGroups;
- },
- [] as GeoInfoGroup[]
- );
+ }, [] as GeoInfoGroup[])
+ .sort((geoInfoGroupA, geoInfoGroupB) => {
+ return getFeatureName(geoInfoGroupA.code).localeCompare(getFeatureName(geoInfoGroupB.code));
+ });
const isTouch = useIsTouchDevice();
return (
-