{"id":21307305,"url":"https://github.com/jdegand/lcogt-angular-frontend","last_synced_at":"2026-05-20T19:34:41.080Z","repository":{"id":167664693,"uuid":"642928814","full_name":"jdegand/LCOGT-angular-frontend","owner":"jdegand","description":"Angular Frontend Rework of my LCOGT-takehomeinterview repo","archived":false,"fork":false,"pushed_at":"2025-09-21T22:09:26.000Z","size":266,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-22T00:10:30.418Z","etag":null,"topics":["angular","tests"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/jdegand.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-19T17:09:13.000Z","updated_at":"2025-09-21T22:09:30.000Z","dependencies_parsed_at":"2024-08-12T22:38:25.130Z","dependency_job_id":null,"html_url":"https://github.com/jdegand/LCOGT-angular-frontend","commit_stats":null,"previous_names":["jdegand/lcogt-angular-frontend"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jdegand/LCOGT-angular-frontend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2FLCOGT-angular-frontend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2FLCOGT-angular-frontend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2FLCOGT-angular-frontend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2FLCOGT-angular-frontend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdegand","download_url":"https://codeload.github.com/jdegand/LCOGT-angular-frontend/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2FLCOGT-angular-frontend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33272478,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-20T15:12:43.734Z","status":"ssl_error","status_checked_at":"2026-05-20T15:12:42.300Z","response_time":356,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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","tests"],"created_at":"2024-11-21T16:31:12.228Z","updated_at":"2026-05-20T19:34:41.036Z","avatar_url":"https://github.com/jdegand.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LCOGT Angular Frontend\n\nThis is a conversion of [my previous solution](https://github.com/jdegand/LCOGT-takehomeinterview) to a past interview test from [LCOGT](https://github.com/LCOGT).\n\nNow, the frontend is separate from the server and requires the json branch of the [express backend](https://github.com/jdegand/LCOGT-takehomeinterview) to work.  See the [how to use section](#how-to-use) for more. \n\nThis frontend also works with a [Spring Boot backend](https://github.com/jdegand/LCOGT-spring-backend).\n\n## Screenshots\n\n![](screenshots/LCOGT-angular-frontend-homepage.png \"Homepage\")\n\n***\n\n![](screenshots/LCOGT-angular-frontend-detail-page.png \"Planet Details Page\")\n\n***\n\n![](screenshots/LCOGT-angular-frontend-add-form.png)\n\n***\n\n![](screenshots/LCOGT-angular-frontend-async-validator-on-blur.png \"Async validator for name on blur\")\n\n***\n\n![](screenshots/LCOGT-angular-frontend-validation-on-blur.png)\n\n***\n\n![](screenshots/LCOGT-angular-frontend-validation-on-submit.png \"Required errors on submit and other errors persist\")\n\n***\n\n## Goal\nCreate a web application where a user can view and add planets to a database.\n\n### Estimated time for completion:\n2-4 Hours\n\n### Instructions\nUse whatever programming language/framework that is most comfortable to you. The deliverable\nproduct should be the sourcecode to a runnable web application with all the requirements met.\nThe database should be blank: you do not need to provide any data with the deliverable.\n\nPlace any special setup instructions in a file called SETUP.\n\nUsing github, you should fork this repository ([Github: how to fork a repository](https://help.github.com/articles/fork-a-repo/)) and add the code you have written to it. When you are done, open a pull request. It will then be reviewed.\n\n## Requirements\n\n#### The homepage\n\nThe homepage should contain a list or table of the planets that have been added to the database\nalong with their name, size, distance and ordinality.\n\nFor example:\n\n    Ordinality  Name     Size    Distance\n    1           Mercury  0.05    0.34\n    2           Venus    0.08    0.72\n\nThe name of the object should link to that object's detail page.\n\n#### The input form\n\nA simple form for adding a planet to the database. The form should have 5 inputs:\nName, Size (in Earth Masses), Distance (from the sun, In Astronomical Units), Ordinality (Mercury: 1, Neptune: 8)\nand Description.\n\nFor example:\n\n          ____          ____              ____                ____\n    Name |____|   Size |____|   Distance |____|   Ordinality |____|\n                  __________________________________\n    Description: |                                  |\n                 |                                  |\n                 |__________________________________|\n     ______\n    |SUBMIT|\n\nName and ordinality should be unique. Size, Ordinality and Distance should be restricted to numerical input.\n\n#### The detail page\nThe detail page should simply display all the available information about the planet.\n\nFor example:\n\n    Mars\n    Mars is the dry and inhospitable 4th planet from the Sun. It is here that Matt Damon\n    grew potatoes using his own poop.\n\n    Ordinality: 4\n    Size: 0.107 Earth Masses\n    Distance: 1.41 AU\n\n### Hints\n\n1. Use sqlite/memory/flat files instead of something like mysql or postgresql to store data. This will make the setup much less complicated.\n\n2. Don't worry about styling: the pages don't have to be pretty, just functional.\n\n### Bonus\nProvide an application that can serve multiple users, with a backend component as opposed to a pure client side application.\n\n***\n\n## Built With\n\n- [Angular CLI](https://github.com/angular/angular-cli) version 15.2.5.\n- [Angular](https://angular.io/)\n\n## How to Use\n\nThe Express application runs by default on `localhost:8080` and has the following endpoints:\n\n - `http://localhost:8080` - returns all planet entries.\n - `http://localhost:8080/planets` - endpoint to post a new planet in the database\n - `http://localhost:8080/planets/detail/:name` - returns a single planet entry \n\n### Running the Express Backend Application\n\nYou can clone my the whole [repo](https://github.com/jdegand/LCOGT-takehomeinterview) and checkout to the json branch or just clone the json branch.  \n\n```bash \n\ngit clone https://github.com/jdegand/LCOGT-takehomeinterview.git -b json --single-branch\n\n# cd into the directory\nnpm install\n\nnpm start\n```\n\nYou can verify the API is working by visiting http://localhost:8080 in\nyour browser or another HTTP client.\n\n### Running the Angular Application\n\nRun the express application first.  Use two terminals.  \n\n```bash\n\ngit clone https://github.com/jdegand/LCOGT-angular-frontend.git\n\n# cd into the directory\nnpm install \n\nnpm start\n\n# For tests -\u003e karma-firefox-launcher included -\u003e install correct launcher for your browser\n\nng test\n```\n\n## Thoughts\n\n- Rebuilding something you have already done in a different way can reveal errors and edge-cases.\n- My original regex implementation for the size and distance fields was flawed. One cause of error was using {0,3} versus {1,3}.  {1,3} includes 0.  By using {0,3} you match for a number of length 3 only.   \n- Regex is probably still flawed.  It can be tough to get a regex working without much trial and error.  Plus, I had not setup testing at the time I worked on the regex.  \n- It was simpler to implement the validation for the size and distance fields on the Spring Boot backend with the @Digits annotation.  \n- I didn't focus on validating whether the name was unique in the Express implementation.\n- In this project, I used an async name validator to make sure each name was unique before submission.  This is a better implementation than allowing submission only to have to send an error (409) back to the client.\n- Typically, I code the backend first.  Since I planned on converting my Express server to a Spring Boot server, I started with the frontend.  I had to convert my Express server to send json.  I had coupled the server with the template in the previous implementation.  I changed the port to 8080 and added the CORS package to the Express server. \n- I changed the backend object to use `id` versus `planetId`. This change allows the planet interface to be used in more places in the frontend.\n- You could put the interfaces (entries, planet) inside their own folder.  Imports would have to updated. \n- In converting to Spring Boot, I found that a change may have been necessary to the `homepage.component.ts` file. I wrapped the data returned from the get all planets route in an entries key to help with Typescript typing.  My Spring Boot conversion did not wrap all planets in an entries key until I changed the return for the all planets route to use a Map, so no changes were necessary in the frontend.  \n- The async validator works but I need to research more about best practices as the implementation can be improved.  \n- Some of the recent changes in Angular seem to be trying to limit callback usage.  See [RxJS](https://rxjs.dev/deprecations/subscribe-arguments) documentation for an example.  \n- I added karma-firefox-launcher and added tests.\n- I went through a lot of iterations in trying to test the nameAsyncValidator.  It was difficult to find a suitable example that I could learn from.  Adding to the difficulty was the validator's setTimeout. \n\n## Useful Resources\n\n- [Stack Overflow](https://stackoverflow.com/questions/63362117/how-to-add-custom-unique-validator-for-form-values-in-angular-reactive-form) - custom unique validator in angular reactive forms\n- [YouTube](https://www.youtube.com/watch?v=9ZFXXMFSs8A) - Using Service for HTTP Request | Angular HTTP | Angular 13+\n- [Stack Overflow](https://stackoverflow.com/questions/51149080/angular-5-reactive-form-pattern-validators) - angular pattern validator\n- [Stack Overflow](https://stackoverflow.com/questions/15798594/validate-fields-after-user-has-left-a-field) - validate fields after a user has finished typing\n- [Stack Overflow](https://stackoverflow.com/questions/52167148/use-updateon-blur-in-angular-reactive-forms) - update on blur in angular reactive forms\n- [Stack Overflow](https://stackoverflow.com/questions/2377897/help-with-regex-need-up-to-3-number-after-the-dot) - 3 numbers after decimal regex\n- [Stack Overflow](https://stackoverflow.com/questions/3541750/regular-expression-to-allow-for-number-values-between-1-3-digits) - regex for 1 to 3 digits\n- [YouTube](https://www.youtube.com/watch?v=ZykoMksRQvI) - Everything You Need to Know About Angular Services and Beyond | In-depth tutorial\n- [YouTube](https://www.youtube.com/watch?v=ibn2yAomxp8) - Angular Routing | LazyLoading | AuthGuard | multiple router-outlet | all in one video\n- [Github](https://gist.github.com/eneajaho/17bbcf71c44eabf56d404b028572b97b) - Prettier \n- [HTML Goodies](https://www.htmlgoodies.com/javascript/dynamic-routing-angular/) - dynamic routing\n- [YouTube](https://www.youtube.com/watch?v=9ZFXXMFSs8A) - Using Service for HTTP Request | Angular HTTP | Angular 13+\n- [Blog](https://www.samjulien.com/how-to-use-route-parameters-in-angular) - route parameters in angular\n- [YouTube](https://www.youtube.com/watch?v=BDuMvZHN1Qs) - Angular HTTP API | Part 19 - Subscribing to Observables 1\n- [Stack Overflow](https://stackoverflow.com/questions/1014284/regex-to-match-2-digits-optional-decimal-two-digits) - regex to match 2 digits optional decimal 2 digits\n- [Stack Overflow](https://stackoverflow.com/questions/36307743/limit-numbers-before-and-after-decimal-point-on-input-number) - limit numbers before and after decimal point on input number\n- [RxJS Docs](https://rxjs.dev/deprecations/subscribe-arguments) - subscribe arguments\n- [Blog](https://jasonwatmore.com/post/2019/11/21/angular-http-post-request-examples) - angular http post request examples\n- [YouTube](https://www.youtube.com/watch?v=xbk2-z8gY4M) - Custom async validator | Reactive Forms | Angular 13+\n- [Stack Overflow](https://stackoverflow.com/questions/59917584/angular-service-always-undefined-when-calling-in-async-validator) - angular service undefined in async validator - need to bind 'this'\n- [Stack Overflow](https://stackoverflow.com/questions/37607257/rxjs-get-value-from-observable) - rxjs get value from observable\n- [Stack Overflow](https://stackoverflow.com/questions/56381034/can-set-some-type-for-formcontrol-value) - setting type for formControl value\n- [Github](https://github.com/angular/angular/issues/15741) - FormGroup reset() doesn't reset custom form control #15741\n- [YouTube](https://www.youtube.com/watch?v=Wr2PYMs1P1g) - Retrieving Form Data and Reseting Form | Angular Forms | Angular 13+\n- [UX Movement](https://uxmovement.com/forms/the-best-place-for-error-messages-on-forms/) - best place for error messages on forms\n- [Testim](https://www.testim.io/blog/testing-angular-services/) - testing angular services\n- [Angular Training Rangle](https://angular-training-guide.rangle.io/testing/services/http/using-httptestingmodule) - http testing module\n- [YouTube](https://www.youtube.com/watch?v=ZS1k-hxMnh0) - Part 38 -Angular Unit test case on Http Client or services method | Angular unit test case Tutorials\n- [YouTube](https://www.youtube.com/watch?v=15othucRXcI) - 30. Testing Services which has HttpClient as dependency by using Jasmine Spy - Angular Unit testing\n- [Angular](https://angular.io/guide/http-test-requests) -http test requests\n- [Stack Overflow](https://stackoverflow.com/questions/49039457/angular-error-no-provider-for-activatedroute) - angular error no privder for activatedRoute\n- [Joshua Colvin](https://www.joshuacolvin.net/mocking-activated-route-data-in-angular/) - mocking activated route data in angular\n- [YouTube](https://www.youtube.com/watch?v=HilQRac28gM) - UT Params and query params | Angular 15 | Angular unit testing\n- [Stack Overflow](https://stackoverflow.com/questions/51327641/service-undefined-jasmine-test) - service undefined jasmine test\n- [Codecraft](https://codecraft.tv/courses/angular/unit-testing/asynchronous/) - async unit testing\n- [Stack Overflow](https://stackoverflow.com/questions/73361624/angular-unit-test-how-to-test-reactive-form-reset-method) - test reactive form reset method\n- [Stack Overflow](https://stackoverflow.com/questions/49009135/angular-formbuilder-testing-with-async-validator) - testing with async validator\n- [Stack Overflow](https://stackoverflow.com/questions/60152333/angular-karma-jasmine-testing-form-validation-error) - testing form validation error\n- [YouTube](https://www.youtube.com/watch?v=79kEX6Xmgxc) - Chapter - 29 AsyncValidator unit testing | Angular Unit Testing | Jasmine | Karma\n- [Stack Overflow](https://stackoverflow.com/questions/59121033/is-it-bad-practice-to-use-a-promise-without-reject) - bad practice to use a promise without reject\n- [Stack Overflow](https://stackoverflow.com/questions/46573314/angular-forcing-a-reactive-form-to-be-valid-in-a-unit-test) - forcing a reactive form to be valid in a unit test\n- [Stack Overflow](https://stackoverflow.com/questions/75025593/testing-custom-async-validator/75031815#75031815) - testing custom async validator\n- [DZone](https://dzone.com/articles/writing-and-testing-custom-angular-validators-the) - writing and testing custom angular validators\n- [CodeTuts](https://code.tutsplus.com/angular-fundamentals--CRS-200838c/unit-testing-validators) - unit testing validators\n- [Stack Overflow](https://stackoverflow.com/questions/53696305/how-can-i-make-an-angular-async-validator-timeout) - async validator timeout\n- [Blog](https://www.damirscorner.com/blog/posts/20210917-TestingTimersWithFakeAsync.html) - testing timers with fake async\n- [Github](https://github.com/jasmine/jasmine/issues/1878) - Test case are failing, when testing setTimeout inside function #1878\n- [Stack Overflow](https://stackoverflow.com/questions/41772989/test-a-function-that-contains-a-settimeout) - test a function that contains a setTimeout\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdegand%2Flcogt-angular-frontend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdegand%2Flcogt-angular-frontend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdegand%2Flcogt-angular-frontend/lists"}