{"id":22265196,"url":"https://github.com/vanheemstrasystems/tools-management","last_synced_at":"2025-06-27T02:36:30.751Z","repository":{"id":210866230,"uuid":"727624571","full_name":"vanHeemstraSystems/tools-management","owner":"vanHeemstraSystems","description":"Tools Management","archived":false,"fork":false,"pushed_at":"2023-12-05T09:10:05.000Z","size":8766,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-25T14:16:20.027Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vanHeemstraSystems.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-12-05T08:41:15.000Z","updated_at":"2023-12-05T08:41:55.000Z","dependencies_parsed_at":"2023-12-05T10:25:09.042Z","dependency_job_id":"d0217214-39e4-4bd4-bc59-9feab718d0a5","html_url":"https://github.com/vanHeemstraSystems/tools-management","commit_stats":null,"previous_names":["vanheemstrasystems/tools-management"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/vanHeemstraSystems/tools-management","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanHeemstraSystems%2Ftools-management","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanHeemstraSystems%2Ftools-management/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanHeemstraSystems%2Ftools-management/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanHeemstraSystems%2Ftools-management/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vanHeemstraSystems","download_url":"https://codeload.github.com/vanHeemstraSystems/tools-management/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanHeemstraSystems%2Ftools-management/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262179128,"owners_count":23271171,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-12-03T10:14:25.086Z","updated_at":"2025-06-27T02:36:30.730Z","avatar_url":"https://github.com/vanHeemstraSystems.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Quarto Publish](https://github.com/vanHeemstraSystems/tools-management/actions/workflows/publish.yml/badge.svg)](https://github.com/vanHeemstraSystems/tools-management/actions/workflows/publish.yml)\n\ntools-management\n# Tools Management\n\nCan be read as \"Tools Management\" at https://app.gitbook.com/s/Rs3XPuVclvoj92Exb9AA/\n\nCan be browsed as \"Tools Management\" at https://vanheemstrasystems.github.io/tools-management/\n\nDocumentation of this repository is automatically done with Quarto using GitHub Actions as described at https://github.com/vanHeemstraSystems/quarto-to-github-pages/blob/main/300/300/README.md\n\nBased on \"IT-Tools.tech\" at https://github.com/CorentinTh/it-tools and https://it-tools.tech/\n\nBased on \"Instagraph\" at https://github.com/yoheinakajima/instagraph\n\nBased on \"Stack Exchange\" at https://stackexchange.com/sites\n\nBased on \"create-react-app\" at https://github.com/facebook/create-react-app\n\nBased on \"JSON Editor\" at https://github.com/josdejong/jsoneditor\n\nBased on \"Getting started with React Query\" at https://hasura.io/blog/getting-started-with-react-query/\n\nBased on \"How to Add a JSON Editor to a React + Next.js Application\" at https://levelup.gitconnected.com/simplest-way-to-add-json-editor-to-nextjs-application-6baa71b5b4dd\n\nBased on \"Map Management\" at https://github.com/vanHeemstraSystems/map-management\n\nBased on \"Create a Next.js App\" at https://nextjs.org/learn/basics/create-nextjs-app\n\nBased on \"src Directory\" at https://nextjs.org/docs/pages/building-your-application/configuring/src-directory\n\nBased on \"Moving Pages folder in Next.js application to src folder\" at https://stackoverflow.com/questions/69690382/moving-pages-folder-in-next-js-application-to-src-folder\n\nBased on \"How to Use State in Functional React Components\" at https://www.howtogeek.com/devops/how-to-use-state-in-functional-react-components/\n\nBased on \"How to Style Your React Apps with CSS Like a Pro\" at https://www.freecodecamp.org/news/style-react-apps-with-css/\n\nBased on \"States and componentDidMount() in functional components with Hooks.\" at https://medium.com/@t93/states-and-componentdidmount-in-functional-components-with-hooks-cac5484d22ad\n\nBased on \"HTML React Parser\" at https://github.com/remarkablemark/html-react-parser/blob/master/examples/create-react-app-typescript/src/App.tsx\n\nBased on \"React Class Components to Functional Components With Hooks\" at https://catalins.tech/react-class-components-to-functional-components-with-hooks/\n\nBased on \"How to fix TypeError: Converting circular structure to JSON in JS?\" at https://codedamn.com/news/javascript/how-to-fix-typeerror-converting-circular-structure-to-json-in-js\n\nBased on \"Unable to import svg files in typescript\" at https://stackoverflow.com/questions/44717164/unable-to-import-svg-files-in-typescript\n\nBased on \"How to import SVGs into your NextJS application\" at https://frontend-digest.com/how-to-import-svgs-into-nextjs-8ec6100e613f\n\nThis is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\nHow to use the Plotly.js React component.\n\nBased on \"Fetching Data and Updating State in a React Class\" at https://www.pluralsight.com/guides/fetching-data-updating-state-react-class\n\nBased on \"Creating Dynamic Routes and Components using ReactJS\" at https://meanstackdeveloper.in/creating-dynamic-routes-and-components-using-reactjs.html\n\nBased on \"Isometric diagram\" at https://www.jointjs.com/demos/isometric-diagram\n\nBased on \"How to Move a Square with React Hooks and Styled Components\" at https://medium.com/programming-essentials/how-to-move-a-square-with-react-hooks-and-styled-components-f649847a9635\n\nBased on \"How to Use Fetch with async/await\" at https://dmitripavlutin.com/javascript-fetch-async-await/\n\nBased on \"Harusa GraphQL in Docker\" at https://hasura.io/docs/latest/deployment/deployment-guides/docker/\n\nBased on \"Using Hasura with Docker and a PostgreSQL database - part 1 of 2 - Docker\" at https://blog.alexanderwolf.tech/using-hasura-with-docker-and-a-postgresql-database-part-1-of-2-docker/\n\nBased on \"Auto-Apply Migrations and Metadata\" at https://hasura.io/docs/latest/migrations-metadata-seeds/auto-apply-migrations/\n\nBased on \"export HTTP_PROXY and special characters in passwd\" at https://unix.stackexchange.com/questions/42273/export-http-proxy-and-special-characters-in-passwd\n\nBased on \"Getting Started with Hasura\" at https://www.youtube.com/watch?v=FEk9Li05Ye4\n\nBased on \"hasura/js-sdk\" at https://github.com/hasura/js-sdk\n\nBased on \"Postgres: Schema\" https://hasura.io/docs/latest/schema/postgres/index/\n\nBased on \"[Live Demo] Query JSON Data In Postgres Database | JSONB Data Type In Postgresql\" at https://www.youtube.com/watch?v=PZFiThbuTFg\n\nBased on \"Working with a JSONB Array of Objects in PostgreSQL\" at https://levelup.gitconnected.com/working-with-a-jsonb-array-of-objects-in-postgresql-d2b7e7f4db87\n\nBased on \"How To Implement One to One, One to Many and Many to Many Relationships When Designing A Database.\" at https://medium.com/@emekadc/how-to-implement-one-to-one-one-to-many-and-many-to-many-relationships-when-designing-a-database-9da2de684710\n\nBased on \"SQL Views With PostgreSQL\" at https://towardsdatascience.com/sql-views-with-postgresql-493ba7aa0934\n\nBased on \"How to use GraphQL Alias and Aggregation?\" at https://bitquery.io/blog/graphql-alias-and-aggregation\n\n**NOTE**: Encode your (proxy) password to avoid clashes with unsupported characters (such as '@'), using https://meyerweb.com/eric/tools/dencoder/\n\n**NOTE**: We set the POSTGRES_DB environment variable in the docker file, otherwise it will use the POSTGRES_USER as database name.\n\n**NOTE**: Remove Docker volume 'pgdata' if you want to start postgres with database initialization.\n\n```mermaid\ngraph TD;\n    linkStyle default interpolate basis\n    wan1[\u003ccenter\u003eDSL 100/10 Mb\u003cbr\u003e\u003cbr\u003e10.100.102.1\u003c/center\u003e]---router{\u003ccenter\u003eEdgeRouter-X\u003cbr\u003e\u003cbr\u003e10.20.30.1\u003c/center\u003e}\n    ip((\u003ccenter\u003e\u003cbr\u003eIP\u003cbr\u003e\u003cbr\u003e\u003c/center\u003e))-.-router\n    dns((\u003ccenter\u003e\u003cbr\u003eDNS\u003cbr\u003e\u003cbr\u003e\u003c/center\u003e))-.-router\n    wan2[\u003ccenter\u003eLTE 50/20 Mb\u003cbr\u003e\u003cbr\u003e192.168.1.1\u003c/center\u003e]---router\n    router---|100Mb|ap[\u003ccenter\u003eRT-AC1200\u003cbr\u003e\u003cbr\u003e10.20.30.3\u003c/center\u003e]\n    router---|1Gb|pc(\u003ccenter\u003ePC\u003cbr\u003e\u003cbr\u003e10.20.30.190\u003c/center\u003e)\n    router---|1Gb|switch[\u003ccenter\u003eTL-SG105E\u003cbr\u003e\u003cbr\u003e10.20.30.2\u003c/center\u003e]\n    subgraph red1\n    ap-.-cam1(\u003ccenter\u003eCamera\u003cbr\u003e\u003cbr\u003e10.20.30.171\u003c/center\u003e)\n    ap-.-cam2(\u003ccenter\u003eCamera\u003cbr\u003e\u003cbr\u003e10.20.30.172\u003c/center\u003e)\n    ap-.-phone(\u003ccenter\u003ePhone\u003cbr\u003e\u003cbr\u003e10.20.30.191\u003c/center\u003e)\n    ap-.-ir(\u003ccenter\u003eIR\u003cbr\u003e\u003cbr\u003e10.20.30.180\u003c/center\u003e)\n    end\n    subgraph red2\n    switch---|100Mb|pi1(\u003ccenter\u003eRPi 3B\u003cbr\u003e\u003cbr\u003e10.20.30.150\u003c/center\u003e)\n    switch---|1Gb|pi2(\u003ccenter\u003eRPi 3B+\u003cbr\u003e\u003cbr\u003e10.20.30.151\u003c/center\u003e)\n    switch---|100Mb|nvr(\u003ccenter\u003eNVR\u003cbr\u003e\u003cbr\u003e10.20.30.170\u003c/center\u003e)\n    switch---|1Gb|laptop(\u003ccenter\u003eLaptop\u003cbr\u003e\u003cbr\u003e10.20.30.192\u003c/center\u003e)\n    end\n``` \n\n### Figure: Diagram (needs rework to display the true architecture)\n\nRun as follows:\n\n```\n$ cd containers/app\n$ docker-compose --file docker-compose.dev.yml --project-name tools-management-dev up --build -d\n```\n\n**NOTE**: If you get the following error when browsing the Plotly service: \n\n``````\nUnhandled Runtime Error\nApolloError: Failed to fetch\n``````\n\nKnow that this is most likely caused by the Hasura service not being up and running yet, therefor not able to sent the requested data to the Plotly Service. To fix it, start the Hasura service.\n\n**NOTE**: When you try to login to PostgreSQL database via **pgAdmin** (Recommended), use the following credentials:\n\n- Email Address / Username: = Use the value of PGADMIN_DEFAULT_EMAIL_DEV/PROD as specified in the .env file\n- Password: Use the value of PGADMIN_DEFAULT_PASSWORD_DEV/PROD as specified in the .env file\n\nInside pgAdmin register a new Server using the following credentials:\n\nRight-Click Servers \u003e Register ... Server:\n\nIn tab **General**:\n\n- Name: Use a name like \"tools-management-dev\" (if for development) - REQUIRED\n\nIn tab **Connection**:\n\n- Host name/address: **localhost** if network_mode is host, or **IP of host** otherwise (recommended).\n- Port: = Use the value of port for the container if network_mode is host, or of the host otherwise (recommended), as specified in the docker-compose file =\n- Maintenance database: **postgres**\n- Username: = Use the value of POSTGRES_USER_DEV/PROD as specified in .env file =\n- Password: = Use the value of POSTGRES_PASSWORD_DEV/PROD as specified in .env file =\n\n**NOTE**: When you try to login to Hasura, use the following credentials:\n\n- Admin secret: = Use the value of HASURA_GRAPHQL_ADMIN_SECRET_DEV/PROD as specified in .env file =\n\n## Hasura\n\n### Connect Your First Database\n\nSee http://hostname:hasura-port-number/console/data/manage/connect\n\n- Database Display Name: **Tools Management - Dev** (for development)\n- Data Source Driver: **Postgres**\n- Connect Database Via: **Database URL**\n- Database URL: **postgresql://username:password@hostname:5432/databasename**, use the value of HASURA_GRAPHQL_DATABASE_URL_DEV/PROD as specified in .env file\n\n- Extensions Schema: = stay with the default =\n- Connection Settings: = stay with the default =\n- GraphQL Field Customization: = stay with the default =\n\n**WARNING**: make sure you did not copy ```sample.hasura_metadata.json``` to the Dockerhost as it will confuse it when there is already a ```hasura_metadata.json``` there.\n\n**WARNING**: make sure you did not copy ```sample.hasura_migrations.json``` to the Dockerhost as it will confuse it when there is already a ```hasura_migrations.json``` there.\n\n### Read the Getting Started Docs\n\nRead https://hasura.io/docs/latest/graphql/core/getting-started/first-graphql-query.html?pg=oss-console\u0026plcmt=onboarding#create-a-table\n\n### Watch Our Getting Started Video\n\nWatch https://www.youtube.com/watch?v=ZGKQ0U18USU\n\n### Bookmark Our Course\n\nBookmark https://hasura.io/learn/graphql/hasura/introduction/?pg=oss-console\u0026plcmt=onboarding-checklist\n\n### Define the Schema in Postgres for Our Tools Management Service\n\nThe schema of our tools management service is based on IT-Tools.tech and should follow a nesting alike below:\n\n```\n\t[\n     {\n       id: 1,\n       position: { x: 36,\n       y: 36 }\n     },\n     {\n       id: 2,\n       position: { x: 136,\n       y: 136 }\n     },\n     {\n       id: 3,\n       position: { x: 236,\n       y: 236 }\n     },\n  ]          \n```\nExample of a schema for nodes.\n\n```\n\t [\n     {\n       source: 1,\n       target: 2\n     },\n     {\n       source: 2,\n       target: 3\n     }\n  ]      \n```\nExample of a schema for links.\n\nTaken together, here is the schema for a map (which combines nodes and links):\n\n```\n  id: 1,\n\n  nodes: [\n     {\n       id: 1,\n       position: { x: 36,\n       y: 36 }\n     },\n     {\n       id: 2,\n       position: { x: 136,\n       y: 136 }\n     },\n     {\n       id: 3,\n       position: { x: 236,\n       y: 236 }\n     },\n  ],\n\n  links: [\n     {\n       source: 1,\n       target: 2\n     },\n     {\n       source: 2,\n       target: 3\n     }\n  ]\n\n```\nExample of a schema for an IT tool.\n\n\nNodes are unique, they can only exist once (with the same unique identifier).\n\nLinks are a relation ship between nodes. One link can link to two nodes (source and target).\n\nHence the relationship between a node and a link is **1-to-many**.\n\nIn creating the tables \u0026 views see the following:\n\n- Nodes schema: see containers/app/postgresql/sql/\n\n- Links schema: see containers/app/postgresql/sql/\n\n- Tools schema: see containers/app/postgresql/sql/\n\nTools are a collection of nodes and links.\n\nIn hasura you can - after having connected to the database and tracked the views - now run a query like below to get a JSON output:\n\n```\nquery fetchFirstTool {\n  first_tool: tools_view(where: {name: {_eq: \"first\"}}) {\n    nodes {\n      id\n      position\n    }\n    links {\n      source\n      target\n    }\n  }\n}\n```\n\nExample outcome of above query:\n\n```\n{\n  \"data\": {\n    \"first_tool\": [\n      {\n        \"nodes\": [\n          {\n            \"id\": 1,\n            \"position\": {\n              \"x\": 36,\n              \"y\": 36\n            }\n          },\n          {\n            \"id\": 2,\n            \"position\": {\n              \"x\": 136,\n              \"y\": 136\n            }\n          },\n          {\n            \"id\": 3,\n            \"position\": {\n              \"x\": 236,\n              \"y\": 236\n            }\n          }\n        ],\n        \"links\": [\n          {\n            \"source\": 1,\n            \"target\": 2\n          },\n          {\n            \"source\": 2,\n            \"target\": 3\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\n**TIP**: To format the code, select the code and in Visual Studio Code (after installing the Prettier extension) combine the following keys: CTRL + SHIFT + P. A dialogue window will ask you for what command you want to execute, type \"format\" and from the dropdown options choose \"prettier\". This will format the selected code.\n\nTo be more precise in which file(s) to format, for example when in ```containers/app/it-tools``` you can run the following:\n\n```\n$ npx prettier --write src/app/page.tsx\n```\n\nIt will take the configuration from ```containers/app/it-tools/.prettierrc```\n\nSee for documentation on **Prettier**, https://prettier.io/docs/en/index.html\n\n## 100 - Introduction\n\nSee [README.md](./100/README.md)\n\n## 200 - Requirements\n\nSee [README.md](./200/README.md)\n\n## 300 - Building our Application\n\nSee [README.md](./300/README.md)\n\n## 400 - Conclusion\n\nSee [README.md](./400/README.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvanheemstrasystems%2Ftools-management","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvanheemstrasystems%2Ftools-management","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvanheemstrasystems%2Ftools-management/lists"}