{"id":41342998,"url":"https://github.com/rodekruis/helpful-information","last_synced_at":"2026-01-23T06:53:09.011Z","repository":{"id":59311387,"uuid":"341542593","full_name":"rodekruis/helpful-information","owner":"rodekruis","description":"A web-app for People Affected to lookup useful organizations and information.","archived":false,"fork":false,"pushed_at":"2025-12-19T17:24:25.000Z","size":9667,"stargazers_count":4,"open_issues_count":69,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-12-21T18:43:54.545Z","etag":null,"topics":["angular","cea","google-sheets","humanitarian-aid","static-web-app"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rodekruis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-02-23T12:09:12.000Z","updated_at":"2025-10-14T09:08:08.000Z","dependencies_parsed_at":"2023-10-12T23:34:43.904Z","dependency_job_id":"08628475-546b-4f72-855e-f90d7416f031","html_url":"https://github.com/rodekruis/helpful-information","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/rodekruis/helpful-information","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodekruis%2Fhelpful-information","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodekruis%2Fhelpful-information/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodekruis%2Fhelpful-information/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodekruis%2Fhelpful-information/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rodekruis","download_url":"https://codeload.github.com/rodekruis/helpful-information/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodekruis%2Fhelpful-information/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28682263,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T05:48:07.525Z","status":"ssl_error","status_checked_at":"2026-01-23T05:48:07.129Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","cea","google-sheets","humanitarian-aid","static-web-app"],"created_at":"2026-01-23T06:53:08.452Z","updated_at":"2026-01-23T06:53:08.992Z","avatar_url":"https://github.com/rodekruis.png","language":"TypeScript","readme":"# Helpful Information\n\nA web-app _People Affected_ can use to lookup useful organizations and information.\n\n\u003e ⚠️  \n\u003e To quickly create a new instance, follow the Guide: [How to set up an instance (quickly)](./docs/Guide-How_to_set_up_an_instance.md)\n\n---\n\n## Status\n\nLatest releases and notable changes are in the [CHANGELOG](CHANGELOG.md).\n\n- [![Tests](https://github.com/rodekruis/helpful-information/actions/workflows/tests.yml/badge.svg)](https://github.com/rodekruis/helpful-information/actions/workflows/tests.yml)\n- [![Workflows](https://github.com/rodekruis/helpful-information/actions/workflows/test_workflows.yml/badge.svg)](https://github.com/rodekruis/helpful-information/actions/workflows/test_workflows.yml)\n\n---\n\n## How it works\n\nThe Helpful Information App (HIA) is a web-app that can show a list of 1 or more \"_regions_\", each of which is a separate dataset of structured content. This consists of \"_Offers_\", sorted in \"_Categories_\" and (optional) \"_Sub-Categories_\".\n\nThe web-app is a pre-build, static web-app that lists links to \"regions\", which are all separate data-sources contained in Google Sheets 'files'.\n\nThe different sheets within these 'files' each have a different data-model. So that their content can be used to display in the web-app.\n\nThe contents of these sheets is loaded at runtime by the visitor's browser from the \"Google Sheets API\".\n\n## How to use\n\nOnce the web-app is configured (See [Configuration](#configuration)) and deployed (See [Deployment](#deployment)) its content can be managed via the [Google Sheets interface](https://docs.google.com/spreadsheets).\n\n### Security\n\n\u003e ⚠️ **All content** of the web-app can be controlled by the contents of the Google Sheet in use.\n\nSo take appropriate precautions regarding file-ownership and \"edit\"-permissions of these files and the related Google Accounts.\n\n- Limit the amount of users/Google Accounts that have \"edit\"-permissions to the 'least possible'\n- Don't share the credentials/passwords of these accounts with multiple people\n- Use a strong password on these Google Accounts\n- Use all possible extra security-features on these Google Accounts, like 2-factor-authentication etc.\n\n### Working with Google Sheets 'files'\n\n\u003e ⚠️ **Everything** is visible on the website on **every** 'save' (so, immediately, most of the times).\n\n- Don't change the _name_ of any sheet.\n- Don't change the _`#tag`s_ in the columns-headers in any sheet, the name/label/heading can be changed/translated.\n- Don't use formatting-tools in Google Sheets (bold/italic/underline/fonts/colors); It will not be used.\n- Don't use the \"insert link\"-feature.  \n  The plain text in a cell should be the full URL.\n\nOptional:\n\n- All columns can be reordered, as long as their `#tag`s remain in their header-cell.\n- You can use the toggle in the \"_Visible?_\"-column to prepare a 'draft' of a row and finally 'publish' by setting it to \"_Show_\".\n- You can use background-colors to mark/highlight any changes or 'flag issues'; These styles will not be used in the web-app.\n\n#### Text formatting\n\nTo support (some) formatting and structuring in some (multi-line) fields, the [Markdown-syntax](https://en.wikipedia.org/wiki/Markdown) can be used.\n\nAn explanation of (a lot of) the features of this syntax can be found in the [Markdown Guide Cheat Sheet](https://www.markdownguide.org/cheat-sheet/). Not _everything_ beyond the \"Basic Syntax\" is supported in all fields.\n\n---\n\n## Getting Started\n\n- Install environment requirements:\n\n  Install the Node.js version specified in the [`.node-version`](.node-version)-file.  \n  To prevent conflicts it is recommended to use a 'version manager'.\n  - [`fnm`](https://github.com/Schniz/fnm#readme) (for Windows/macOS/Linux)\n    After installing, run in this directory:\n\n        fnm use\n\n- Install dependencies (from this directory):\n\n      npm install\n\n- To finish you local set-up, run (required only once):\n\n      npm run setup\n\n- Start in development-mode:\n\n      npm start\n\n- Start in production-mode:\n\n      npm run start:production\n\n## Configuration\n\nSome specific information needs to be configured before use:\n\n- For use in development:  \n  Set these different properties in the [`environment.ts`](./src/environments/environment.ts)-file.\n\n- For use in production:  \n  These values need to be set in the [`.env`](.env.example)-file. Or as ENV-variables via other means.\n\n- For deployments:  \n  The ENV-variables defined in the [`.env.example`](.env.example)-file need to be defined in the build-environment according to the specific deployment-tool/service.  \n  See for example the [GitHub Action workflow (production)](.github/workflows/deploy-production.yml).\n\n### Using the Google Sheets API\n\n- To be able to use the [Google Sheets API](https://developers.google.com/sheets/api) a 'credential' in the shape of an API-key is required.\n- To get an API-key, follow the instructions: [Guide: How to set-up an instance / Create a Google Sheets API-key](docs/Guide-How_to_set_up_an_instance.md#create-a-google-sheets-api-key)\n- Configure the restrictions on the API-key following:  \n  \u003chttps://cloud.google.com/docs/authentication/api-keys#adding_http_restrictions\u003e  \n  Make sure to include _only_ the domains/referrers that will be used.  \n  Also include `http://localhost:4200/*` and `http://localhost:8080/*` to be able to load data during local development. (Or even better; create a separate API-key for that)\n\n## Local development\n\nAs part of the installed dev-dependencies, we use [Prettier](https://prettier.io/) to format our code.  \nTo use these settings without a local setup, use the [Prettier Playground](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEAdK7UwAoEMDO8ABAJ4QCuATkWABa5QDmc+RAllETLXEQDZwAZjCIAHBnD5EGAExoRRJLjyIUYo8iMGUIAW2W9KbRrRHiokgHSYoIADQgFMNtHzJQuSjoDueSgjcUXD5vXBI3BwAjSlwwAGs4GABlXF04ABkOOGRBYPw4KJj4xKTxMA5GZBhKcgKQOF1IuBkZZvSGRnJcZgAxCEpdXBhnJmQQXE0IexBTXT4AdVo2eHwyuCSA5bYAN2WSMbB8CJAOfMocGMZBnLy6gCt8AA8kioEARXIIeBu+fIdxShnMaDShxGQQby2f5GWDzNgybjIAAcAAZoRB8vMYqIxqJ-GdttkHABHT7wbA6USBcb4AC0FmazWm-lJbH8FO61yQuV+dXyujYVRqfNecAAgsMjJFNHBsHBKJkLELag58KKPl9skhqiqQDBcJE4QjaMgAEwOaq4Nh8CoAYT0XPGfD403I+QAKgbAjy-iBtrUAJJQVqwJJgIyiGBi4NJGAkAQ-fIAXyTQA) in your browser.\n\nWhen installing locally, we use [husky](https://typicode.github.io/husky/#/?id=faq) to automate the formatting and testing (when not already handled by your editor).\n\n### Local API\n\nTo use a local API, without the need for any Google account/credentials:\n\n1. Update the local [`environment.ts`](src/environments/environment.ts)-file with:\n\n   ```ts\n       regions: 'test-local-1',\n       regionsLabels: 'Test Local 1',\n       regionsSheetIds: 'test-sheet-id-1',\n\n       google_sheets_api_key: '\u003ccan be anything, will be ignored\u003e';\n       google_sheets_api_url: 'http://localhost:3001',\n   ```\n\n2. Run (in a separate process/terminal):\n\n   npm run serve:local-data\n\n3. Adjust the JSON-files in the [`data`](data/)-directory to try out different content.\n\n### Testing\n\nAutomated tests are configured and can be run (once) with:\n\n    npm test\n\nDuring development, an automated watch-process can be run with:\n\n    npm run test:watch\n\n### Recommended tools\n\n- [Workspace recommendations for VS Code](.vscode/extensions.json)\n  When you use [VS Code](https://code.visualstudio.com/) and go to: \"_Extensions_\" and use the filter: \"_Recommended_\";\n  A list should be shown and each extension can be installed individually.\n\n### Libraries/frameworks in use\n\n- [Ionic v8](https://ionicframework.com/docs/)\n  \u003e ⚠️ The [`Ionicons`](https://ionic.io/ionicons) icon-set is NOT included in the final build, so cannot be used 'by default'. Icons can be added manually.\n- [Angular v18](https://v18.angular.io/docs/)\n- [`ngx-markdown`](https://www.npmjs.com/package/ngx-markdown) is used to process Markdown-content into HTML. _No_ optional dependencies are included/used.\n\n### Updating dependencies\n\nMost (development-)dependencies in this repository are monitored by the GitHub [Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates) service, to keep them up-to-date.  \nUnfortunately most individual dependencies are 'linked' to related dependencies that need to stay 'in sync'.\n\nTo update all Angular and ESLint related dependencies, run:\n\n    npm run upgrade:angular\n\n---\n\n## Data Model\n\nBased on the data fetched from the Google Sheets, an internal data-structure is build. This is used to render the interface.\n\nThe following are _illustrations_ only, to help get an overview, it might not be up-to-date with the actual code.\n\n### Data Model (internal)\n\n\u003e The code below can be easily edited/previewed using the [Mermaid.live](https://mermaid.live) editor.\n\n```mermaid\n%%{ init:{ 'theme':'base', 'themeVariables':{'lineColor':'blue'} }}%%\n\nclassDiagram\n  class App {\n    ENV\n    regions\n    regionLabels\n    regionSheetIds\n  }\n\n  class Region {\n    slug\n    label\n    googleSheetId\n  }\n\n  class Category {\n    int categoryID\n    slug\n    bool isVisible\n    icon\n    description\n  }\n\n  class SubCategory {\n    int subCategoryID\n    slug\n    bool isVisible\n    icon\n    description\n  }\n\n  class Offer {\n    int categoryID\n    int subCategoryID\n    chapterName\n    chapterSlug\n    bool isVisible\n    int offerId\n    slug\n    offerName\n    icon\n    + ...many more properties\n  }\n\n  class QASet {\n    int categoryID\n    int subCategoryID\n    bool isVisible\n    int id\n    slug\n    parentSlug\n    question\n    answer\n    Date updated\n    bool isHighlight\n    array~QASet~ children\n  }\n\n  direction LR\n    App -- \"1..*\" Region\n    Region -- \"1..*\" Category\n    Category -- \"0..*\" SubCategory\n    SubCategory -- \"0..*\" Offer\n    SubCategory -- \"0..*\" QASet\n    QASet -- \"0..*\" QASet : children\n```\n\n### Data Model (external)\n\n\u003e The code below can be easily edited/previewed using the [Mermaid.live](https://mermaid.live) editor.\n\n```mermaid\n%%{ init:{ 'theme':'base', 'themeVariables':{'lineColor':'blue'} }}%%\n\nclassDiagram\n  class GoogleSheet {\n    string id\n  }\n  class ReferralPage {\n    Key-Value rows [];\n  }\n\n  class Help {\n    Documentation only\n  }\n  class Options {\n    Only for uses in the Sheet itself\n  }\n\n  direction TB\n    GoogleSheet -- \"1\" ReferralPage\n    GoogleSheet .. \"1\" Help\n    GoogleSheet .. \"1\" Options\n\n    GoogleSheet -- \"1\" Categories\n    GoogleSheet -- \"1\" SubCategories\n    GoogleSheet -- \"1\" Offers\n    GoogleSheet -- \"1\" Q_As\n\n    Categories : rows []\n    SubCategories : rows []\n    Offers : rows []\n    Q_As : rows []\n```\n\n---\n\n## Features\n\n### Build level configuration\n\nSee the options in the [`.env.example`](.env.example)-file.\n\nEach Instance:\n\n- can have 1 or multiple Sheet(s), each:\n  - has a unique URL-slug (`[a-z0-9._-]`)\n  - has a human-readable (short) label (can contain capitals, spaces, numbers, emoji, etc.)\n  - has a `Google Spreadsheet ID`, a 44-character string (from: `https://docs.google.com/spreadsheets/d/`**`___SPREADSHEET_ID___`**`/edit?usp=sharing`)\n\n- can have a customized 'color scheme' (and other CSS), by adjusting the contents of the [`overrides.css`](./src/theme/overrides.css)-file.  \n  This needs to be done _before_ building the web-app. (See for example: `[.github/workflows/deploy-staging.yml`](.github/workflows/deploy-staging.yml#L50)).\n\n### Sheet level configuration\n\nSee the options in the \"Referral Page\"-sheet:\n\n- it has a `#KEY`-column with all available properties(Using `#tag.sub-tag`s, from [`RegionDataKey`](./src/app/models/region-data.ts)) and `#VALUE`-column with their current value.\n\n### (Sub-)Category features\n\nEach (Sub-)Category:\n\n- can have a (single line) name\n- can have a URL-slug (`[a-z0-9._-]`);  \n  This _needs_ to be unique within all Categories; For each Sub-Category it needs to be unique within its parent Category _only_.\n- can have a multi-line description, [Markdown syntax](#text-formatting) can be used for structure/formatting.\n- can have an (absolute/relative/data-) URL for an icon\n- can be hidden by setting the \"**Visible?**\"-column to `Hide`.\n\n### Offer features\n\nEach Offer\n\n- needs to have a `Category ID` and a `Sub-Category ID` set.\n- can have a URL-slug (`[a-z0-9._-]`);  \n  This _needs_ to be unique within its parent Sub-Category _only_.\n- can be hidden by setting the \"**Visible?**\"-column to `Hide`.\n- can have a Chapter-name (in plain/normal text);  \n  This will be used to group Offers within their parent Sub-Category.\n- can have some multi-line fields, [Markdown syntax](#text-formatting) can be used for structure/formatting in those.\n\n### Q\u0026A features\n\nEach Q\u0026A-set\n\n- needs to have a `Category ID` and a `Sub-Category ID` set.\n- needs to have an `Answer` value\n- can have a URL-slug (`[a-z0-9._-]`);  \n  This _needs_ to be unique within all Q\u0026A-sets.\n- can be hidden by setting the \"**Visible?**\"-column to `Hide`.\n- can be shown as a Sub-Question by setting the `Parent`-column to the Slug of another Question.\n- can have a \"(last) updated\"-date set, to indicate its 'freshness'\n- can have a multi-line `Answer`, [Markdown syntax](#text-formatting) can be used for structure/formatting.\n\n#### Highlighted-overview (\"Recent changes\")\n\n- Each Q\u0026A-set can be shown in the Highlighted-overview by setting the \"**Highlighted?**\"-column to `Yes`.\n- All these sets will be shown with their Category/Sub-Category-context (with links).\n- Their \"(last) updated\"-date is shown prominently, for easy scanning/spotting \"what's new?\"\n- The sets with a \"(last) updated\"-date will be shown with the \"most recent\"-date first, those _without_ a date are shown after, in the order they appear in the sheet.\n\n#### Search\n\nUsing the search-input Q\u0026A-sets can be filtered to match 1 or more keywords to the `Question` OR the `Answer` values of a Q\u0026A-set.\n\n- Keywords are case-insensitive, so `Help` will match `help`, `HELP` or `HeLp`\n- Some special characters will be ignored, like `+`, `*`, `[`, `]`, `(`, `)`, etc. Periods (`.`) can be included in keywords to match URLs\n- Each keyword needs to be separated by spaces (not `,` or `;`, etc.)\n- To include spaces in a keyword, surround with: `\"` (double quotes)  \n  For example: `help \"Red Cross\"` will match `help` or `Red Cross`\n\n---\n\n## Deployment\n\nThe web-app can be deployed as a static single-page-app or PWA.\n\n- Make sure the `.env`-configuration is prepared. See: [`.env.example`](.env.example)\n- To generate a directory(`www`) with all HTML, JS, JSON and SVG assets, run:\n\n      npm run build:production\n\n- This directory can be deployed to any hosting-solution (supporting HTTPS), using [the recommended server configuration](https://v13.angular.io/guide/deployment#server-configuration).\n\n### Using Azure Static Web Apps\n\nTo deploy the web-app using [Azure Static Web App service](https://azure.microsoft.com/en-us/services/app-service/static/):\n\n- A GitHub-Actions workflow needs to be defined,  \n  See: [`.github/workflows/deploy-production.yml`](.github/workflows/deploy-production.yml)\n- The configuration of URLs, Headers for the web-app is defined,  \n  in: [`staticwebapp.config.json`](staticwebapp.config.json)  \n  See documentation about the format in [this example configuration file](https://docs.microsoft.com/en-us/azure/static-web-apps/configuration#example-configuration-file)\n\n### Using static file hosting (i.e. Surge.sh, GitHub/GitLab Pages or similar)\n\nTo deploy the web-app using or a static-files web-host, see options at: \u003chttps://jamstack-deploy.vercel.app/\u003e or articles like: \u003chttps://www.hostingadvice.com/how-to/best-static-web-hosting/\u003e.\n\nConfigure and build a 'production'-build of the web-app following the steps [defined at \"Deployment\"](#deployment).\n\nFollow one of these ['guides' from Surge](https://surge.sh/help/#:~:text=Guides).\n\n---\n\n## License\n\nReleased under the Apache 2.0 License. See [LICENSE](./LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodekruis%2Fhelpful-information","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frodekruis%2Fhelpful-information","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodekruis%2Fhelpful-information/lists"}