From d19824ecf53a010b4d7dc517988b96425a4954f5 Mon Sep 17 00:00:00 2001 From: Jessica Cheng <31293603+JessicaLucindaCheng@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:39:40 -0800 Subject: [PATCH 1/4] Merge branch 'gh-pages' into update-feature-homepage-launch-on-Nov-19-2024 --- .github/ISSUE_TEMPLATE/add-github-handle.md | 15 +- ...nities-of-practice-information-updates.yml | 32 +- .../correct-misspelling-on-website-page.md | 31 + .../img-tag-refactor-on-website.md | 2 +- .github/ISSUE_TEMPLATE/post-an-open-role.md | 12 + .../pre-work-template---design.md | 4 +- .../ISSUE_TEMPLATE/pre-work-template--dev.md | 7 +- ...project-profile-card-review-and-update.yml | 16 + .../project-profile-leader-updates---add.md | 44 + ...project-profile-leader-updates---remove.md | 38 + .../ISSUE_TEMPLATE/skills-issue--developer.md | 659 + .github/ISSUE_TEMPLATE/spell-check-audit.md | 6 +- ...eature-or-new-content-for-hackforla-org.md | 2 +- .github/dependabot.yml | 8 + .github/pull_request_template.md | 53 +- .github/workflows/codeql-create-issues.yml | 51 + .github/workflows/codeql-scan-job.yml | 77 + .github/workflows/codeql.yml | 77 +- .github/workflows/issue-trigger.yml | 68 +- .github/workflows/lint-scss.yml | 2 +- .github/workflows/move-closed-issues.yaml | 25 +- .github/workflows/pr-instructions.yml | 5 +- .github/workflows/pr-verification.yml | 16 + .github/workflows/pull-request-trigger.yml | 69 +- .github/workflows/schedule-daily-1100.yml | 4 +- .github/workflows/schedule-fri-0700.yml | 11 +- .github/workflows/schedule-monthly.yml | 98 +- .github/workflows/update-label-directory.yml | 50 + .github/workflows/vrms-data.yml | 2 +- .github/workflows/wr-schedule-monthly.yml | 20 +- CONTRIBUTING.md | 233 +- _config.yml | 2 + _data/external/_wins-data.json | 2 +- _data/external/github-data.json | 16185 +++++++++++----- _data/external/vrms_data.json | 2 +- _data/external/wins-data.json | 3 +- _data/internal/communities/data-science.yml | 4 +- _data/internal/communities/engineering.yml | 6 +- _data/internal/communities/operations.yml | 29 +- .../communities/product-management.yml | 4 +- _data/internal/communities/ui-ux.yml | 6 +- _data/internal/former-sponsors-partners.yml | 3 + _data/internal/partners.yml | 5 + _data/internal/privacy-policy.yml | 6 +- _data/internal/toolkitresources.yml | 2 +- _guide-pages/2FA.html | 2 +- _includes/about-page/about-card-news.html | 8 +- _includes/calendar.html | 10 - _includes/current-guides.html | 4 +- .../events-page/header-container-content.html | 34 +- .../events-page/right-col-content-check.html | 32 + _includes/events-page/right-col-content.html | 10 +- _includes/resource-card.html | 14 +- _includes/svg/icon-github-color.svg | 78 - _includes/svg/icon-github-small.svg | 71 - _includes/svg/icon-slack-color.svg | 33 - _layouts/default-markdown.html | 1 - _layouts/default.html | 1 - .../citizen-engagement-card.yml | 0 .../civic-tech-infrastructure-card.yml | 0 .../diversity-equity-inclusion-card.yml | 0 .../environment-card.yml | 0 .../justice-card.yml | 0 .../social-safety-net-card.yml | 0 .../vote-representation-card.yml | 0 .../workforce-development-card.yml | 0 _projects/100-automations.md | 1 + _projects/311-data.md | 21 +- _projects/ballot-nav.md | 5 + _projects/brigade-organizers-playbook.md | 7 +- _projects/civic-opportunity-project.md | 1 + _projects/civic-tech-index.md | 16 + _projects/civic-tech-jobs.md | 125 +- _projects/civic-tech-structure.md | 5 + _projects/design-systems.md | 14 + _projects/ems-triage-tracker.md | 21 +- _projects/engage.md | 4 + _projects/expunge-assist.md | 53 +- _projects/food-oasis.md | 39 +- _projects/guides-team.md | 31 +- _projects/heart.md | 11 +- _projects/hellogov.md | 3 +- _projects/home-unite-us.md | 39 +- _projects/public-tree-map.md | 2 +- _projects/tdm-calculator.md | 40 + _projects/tech-work-experience.md | 21 +- _projects/vrms.md | 8 + _projects/website.md | 82 +- _projects/youthjusticenav.md | 1 + .../components/_communities-of-practice.scss | 3 +- _sass/components/_project-page.scss | 9 +- _sass/components/_toolkit.scss | 16 +- _sass/elements/_containers.scss | 1 + _sass/elements/_dropdown_filters.scss | 30 +- _sass/elements/_old_dropdown_filters.scss | 2 +- _sass/elements/_search-bar.scss | 12 + _sass/layouts/_main.scss | 2 +- _sass/variables/_layout.scss | 3 + .../code-for-america.svg | 0 assets/images/partners/atwater-village.png | Bin 0 -> 27068 bytes .../technologies-icons/github-icon-1.svg | 1 - assets/js/api-actionnetwork.js | 117 - assets/js/communities-of-practice.js | 60 + assets/js/current-projects.js | 86 +- assets/js/elements/noResultsMessageFilter.js | 17 +- assets/js/events-check.js | 45 + assets/js/events.js | 27 +- assets/js/project-meetings.js | 15 +- assets/js/project.js | 90 +- assets/js/right-col-content-check.js | 25 + assets/js/right-col-content.js | 121 +- assets/js/utility/api-events.js | 9 +- assets/js/utility/vrms-events.js | 79 + assets/js/wins.js | 42 +- assets/pdfs/Expunge-Assist-One-Sheet.pdf | Bin 0 -> 69033 bytes cspell.json | 19 +- .../move-closed-issues/move-closed-issues.js | 19 + .../move-closed-issues/sort-closed-issues.js | 52 +- .../pr-instructions/create-instruction.js | 58 +- .../pr-instructions/post-comment.js | 1 - .../pr-instructions-contrib-template.md | 4 +- .../pr-instructions/pr-instructions-header.md | 3 + .../pr-instructions-template.md | 4 +- .../check-labels.js | 90 +- .../post-labels-comment.js | 44 +- .../check-complexity-eligibility.js | 449 + .../developer-complexity-reminder.md | 12 + .../draft-label-reminder.md | 3 + .../multiple-issue-reminder.md | 6 + .../preliminary-update-comment.js | 270 +- .../unassign-from-NIA.md | 5 + .../check-existing-issues.js | 62 + .../create-codeql-issues/create-new-issues.js | 52 + .../create-codeql-issues/fetch-alerts.js | 36 + .../create-codeql-issues/issue-body.md | 27 + .../add-feature-branch-comment.js | 44 + .../feature-branch-comment.md | 5 + .../hide-feature-branch-comment.js | 65 + github-actions/trigger-pr-target/verify-pr.js | 37 + .../trigger-pr/check-linked-issue.js | 54 + .../add-update-label-weekly/add-label.js | 311 +- .../github-data/contributors-data.js | 374 - .../github-data/get-project-data.js | 46 +- .../github-data/package-lock.json | 464 +- .../trigger-schedule/github-data/package.json | 12 +- .../list-inactive-members/create-new-issue.js | 67 +- .../get-contributors-data.js | 185 + .../list-inactive-members/inactive-members.md | 3 +- .../trim-inactive-members.js | 219 + .../utils/_data/inactive-members.json | 74 + .../utils/_data/label-directory.json | 830 + .../utils/_data/status-field-ids.js | 86 + github-actions/utils/add-team-member.js | 27 + github-actions/utils/check-team-membership.js | 33 + github-actions/utils/find-linked-issue.js | 36 +- github-actions/utils/get-team-members.js | 35 + github-actions/utils/get-timeline.js | 55 +- github-actions/utils/hide-issue-comment.js | 29 + github-actions/utils/mutate-issue-status.js | 46 + github-actions/utils/query-issue-info.js | 58 + .../utils/retrieve-label-directory.js | 34 + .../utils/update-label-directory.js | 164 + google-apps-scripts/gh-requests/Code.js | 19 +- .../wins-form-responses/Code.js | 48 +- pages/communities-of-practice.html | 16 +- pages/events-check.html | 54 + pages/getting-started.html | 2 +- pages/index.html | 1 - pages/join-us.html | 2 +- pages/program-areas.html | 49 +- pages/project-meetings.html | 5 +- pages/sitemap.html | 6 +- redirections/github.md | 2 +- 173 files changed, 17333 insertions(+), 7136 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/correct-misspelling-on-website-page.md create mode 100644 .github/ISSUE_TEMPLATE/post-an-open-role.md create mode 100644 .github/ISSUE_TEMPLATE/project-profile-leader-updates---add.md create mode 100644 .github/ISSUE_TEMPLATE/project-profile-leader-updates---remove.md create mode 100644 .github/ISSUE_TEMPLATE/skills-issue--developer.md create mode 100644 .github/workflows/codeql-create-issues.yml create mode 100644 .github/workflows/codeql-scan-job.yml create mode 100644 .github/workflows/pr-verification.yml create mode 100644 .github/workflows/update-label-directory.yml create mode 100644 _data/internal/former-sponsors-partners.yml delete mode 100644 _includes/calendar.html create mode 100644 _includes/events-page/right-col-content-check.html delete mode 100644 _includes/svg/icon-github-color.svg delete mode 100644 _includes/svg/icon-github-small.svg delete mode 100644 _includes/svg/icon-slack-color.svg rename {_data/internal/program-areas => _program-areas}/citizen-engagement-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/civic-tech-infrastructure-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/diversity-equity-inclusion-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/environment-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/justice-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/social-safety-net-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/vote-representation-card.yml (100%) rename {_data/internal/program-areas => _program-areas}/workforce-development-card.yml (100%) rename assets/images/{sponsors => former-sponsors-partners}/code-for-america.svg (100%) create mode 100644 assets/images/partners/atwater-village.png delete mode 100644 assets/images/technologies-icons/github-icon-1.svg delete mode 100644 assets/js/api-actionnetwork.js create mode 100644 assets/js/communities-of-practice.js create mode 100644 assets/js/events-check.js create mode 100644 assets/js/right-col-content-check.js create mode 100644 assets/js/utility/vrms-events.js create mode 100644 assets/pdfs/Expunge-Assist-One-Sheet.pdf create mode 100644 github-actions/move-closed-issues/move-closed-issues.js create mode 100644 github-actions/pr-instructions/pr-instructions-header.md create mode 100644 github-actions/trigger-issue/add-preliminary-comment/check-complexity-eligibility.js create mode 100644 github-actions/trigger-issue/add-preliminary-comment/developer-complexity-reminder.md create mode 100644 github-actions/trigger-issue/add-preliminary-comment/draft-label-reminder.md create mode 100644 github-actions/trigger-issue/add-preliminary-comment/multiple-issue-reminder.md create mode 100644 github-actions/trigger-issue/add-preliminary-comment/unassign-from-NIA.md create mode 100644 github-actions/trigger-issue/create-codeql-issues/check-existing-issues.js create mode 100644 github-actions/trigger-issue/create-codeql-issues/create-new-issues.js create mode 100644 github-actions/trigger-issue/create-codeql-issues/fetch-alerts.js create mode 100644 github-actions/trigger-issue/create-codeql-issues/issue-body.md create mode 100644 github-actions/trigger-issue/feature-branch-comment/add-feature-branch-comment.js create mode 100644 github-actions/trigger-issue/feature-branch-comment/feature-branch-comment.md create mode 100644 github-actions/trigger-issue/feature-branch-comment/hide-feature-branch-comment.js create mode 100644 github-actions/trigger-pr-target/verify-pr.js create mode 100644 github-actions/trigger-pr/check-linked-issue.js delete mode 100644 github-actions/trigger-schedule/github-data/contributors-data.js create mode 100644 github-actions/trigger-schedule/list-inactive-members/get-contributors-data.js create mode 100644 github-actions/trigger-schedule/list-inactive-members/trim-inactive-members.js create mode 100644 github-actions/utils/_data/inactive-members.json create mode 100644 github-actions/utils/_data/label-directory.json create mode 100644 github-actions/utils/_data/status-field-ids.js create mode 100644 github-actions/utils/add-team-member.js create mode 100644 github-actions/utils/check-team-membership.js create mode 100644 github-actions/utils/get-team-members.js create mode 100644 github-actions/utils/hide-issue-comment.js create mode 100644 github-actions/utils/mutate-issue-status.js create mode 100644 github-actions/utils/query-issue-info.js create mode 100644 github-actions/utils/retrieve-label-directory.js create mode 100644 github-actions/utils/update-label-directory.js create mode 100644 pages/events-check.html diff --git a/.github/ISSUE_TEMPLATE/add-github-handle.md b/.github/ISSUE_TEMPLATE/add-github-handle.md index fa9aa8b308..4519cab7c3 100644 --- a/.github/ISSUE_TEMPLATE/add-github-handle.md +++ b/.github/ISSUE_TEMPLATE/add-github-handle.md @@ -2,8 +2,9 @@ name: github-handle in project file about: For adding github-handle to member data in a project file title: Add github-handle for [INSERT NAME] in [INSERT PROJECT FILE] -labels: 'good first issue, P-Feature: Project Info and Page, ready for dev lead, role: - back end/devOps, role: front end, size: 0.25pt' +labels: 'Complexity: Small, feature: spelling, good first issue, P-Feature: Project + Info and Page, ready for merge team, role: back end/devOps, role: front end, size: + 0.5pt, size: 0.25pt' assignees: '' --- @@ -11,7 +12,7 @@ assignees: '' ### Prerequisite 1. Be a member of Hack for LA. (There are no fees to join.) If you have not joined yet, please follow the steps on our [Getting Started Page](https://www.hackforla.org/getting-started). 2. Before you claim or start working on an issue, please make sure you have read our [How to Contribute to Hack for LA Guide](https://github.com/hackforla/website/blob/7f0c132c96f71230b8935759e1f8711ccb340c0f/CONTRIBUTING.md). - + ### Overview We need to create a single variable `github-handle` to hold the github handle for each member of the leadership team. Eventually `github-handle` will replace the `github` and `picture` variables, reducing redundancy in the project file. @@ -24,7 +25,7 @@ We need to create a single variable `github-handle` to hold the github handle fo with ``` - name: [INSERT MEMBER NAME] - github-handle: + github-handle: ``` - [ ] Do not use a tab to indent `github-handle`. YAML doesn't allow tabs; it requires spaces. - [ ] Using docker, confirm that the appearance of the project webpage is unchanged at all screen sizes. The project webpage URL can be found below under Resources. @@ -33,9 +34,9 @@ with - [ ] Release the dependency for this issue in #5441. If all the dependencies have been completed, close that issue. ### Resources/Instructions -https://github.com/hackforla/website/wiki/project.md-file-template -https://jekyllrb.com/ -For QA to validate change: https://github.com/hackforla/website/blob/gh-pages/[INSERT-PATH-TO-PROJECT-FILE] +https://github.com/hackforla/website/wiki/project.md-file-template +https://jekyllrb.com/ +For QA to validate change: https://github.com/hackforla/website/blob/gh-pages/_projects/[INSERT_PROJECT_FILE]?plain=1 Project Webpage: https://www.hackforla.org/projects/[INSERT-PROJECT-FILENAME-WITHOUT-.MD-EXTENSION] - This issue is part of #5441. diff --git a/.github/ISSUE_TEMPLATE/communities-of-practice-information-updates.yml b/.github/ISSUE_TEMPLATE/communities-of-practice-information-updates.yml index 0ea1d77aea..4a0017f19e 100644 --- a/.github/ISSUE_TEMPLATE/communities-of-practice-information-updates.yml +++ b/.github/ISSUE_TEMPLATE/communities-of-practice-information-updates.yml @@ -1,9 +1,7 @@ name: Communities of Practice information updates description: CoP leads use this issue to make changes to Leadership members and contact info -title: 'Communities of Practice information updates: [INSERT NAME OF Community of - Practice]' +title: 'Communities of Practice information updates: [INSERT NAME OF Community of Practice]' labels: ['role: product', 'P-Feature: Communities of Practice', 'time sensitive', 'Complexity: Missing', 'size: missing'] - body: - type: markdown attributes: @@ -20,9 +18,24 @@ body: - type: markdown attributes: value: "Change Description: NO" - - type: markdown + - type: dropdown + attributes: + label: "Change Leadership Type" + options: + - "YES" + - "NO" + description: "If YES on Change Leadership Type, choose the Leadership Type; if NO, leave the field with the NA value:" + validations: + required: true + - type: dropdown attributes: - value: "Change Leadership Type: NO" + label: "Leadership Type" + options: + - "N/A" + - "Mentor Led" + - "Community Led" + default: 0 + description: "Select the type of leadership if applicable." - type: markdown attributes: value: "Change Slack Link: NO" @@ -58,11 +71,10 @@ body: Title: GitHub Handle: Slack Member ID: - - type: markdown - attributes: - value: "### Resources" - type: markdown attributes: value: | - folder where files are in the repo: https://github.com/hackforla/website/tree/gh-pages/_data/internal/communities - where you can see the live page: https://www.hackforla.org/communities-of-practice + ### Resources + * Folder where files are in the repo: https://github.com/hackforla/website/tree/gh-pages/_data/internal/communities + * Where you can see the live page: https://www.hackforla.org/communities-of-practice + * If you need to update your meeting times, names, dates, or frequency, please see the [VRMS User Guide](https://github.com/hackforla/VRMS/wiki/User-Guide). The HackforLA.org website gets the meeting times from the updates made to each Community of Practice's meeting data in vrms.io \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/correct-misspelling-on-website-page.md b/.github/ISSUE_TEMPLATE/correct-misspelling-on-website-page.md new file mode 100644 index 0000000000..7e0edb47a1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/correct-misspelling-on-website-page.md @@ -0,0 +1,31 @@ +--- +name: Correct misspelling on Website Page +about: Describe this issue template's purpose here. +title: Correct misspelling in [REPLACE WITH NAME OF PAGE] page +labels: 'Feature Missing, feature: spelling, good first issue, role: back end/devOps, + role: front end, size: 0.25pt, time sensitive' +assignees: '' + +--- + +### Prerequisite +1. Be a member of Hack for LA. (There are no fees to join.) If you have not joined yet, please follow the steps on our [Getting Started page](https://www.hackforla.org/getting-started). +2. Please make sure you have read our **[Hack for LA Contributing Guide](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md)** before you claim/start working on an issue. + +### Overview +Our website needs to be free of misspellings so that our reputation for quality is maintained. In this issue a misspelling in the [REPLACE WITH WHERE] on the [REPLACE WITH NAME OF PAGE] page will be corrected. + +### Action Items +- [ ] For the file `[REPLACE WITH DIRECTORY & NAME OF FILE (e.g., /pages/communities-of-practice.html)]`, correct the spelling from "[REPLACE WITH MISSPELLED WORD]" to "[REPLACE WITH CORRECT SPELLED WORD]", so + ``` + [REPLACE WITH CURRENT CODE] + ``` + becomes + ``` + [REPLACE WITH FUTURE CODE - WHAT IT WILL LOOK LIKE AFTER ITS FIXED] + ``` +- [ ] Use Docker to test changes locally, in both desktop and mobile views + +### Resources +Website page with issue: [REPLACE WITH URL OF PAGE ON WEBSITE] +File on GitHub: https://github.com/hackforla/website/blob/gh-pages/REPLACE WITH DIRECTORY & NAME OF FILE (e.g., /pages/communities-of-practice.html)] diff --git a/.github/ISSUE_TEMPLATE/img-tag-refactor-on-website.md b/.github/ISSUE_TEMPLATE/img-tag-refactor-on-website.md index 0475871cc8..92d18990ea 100644 --- a/.github/ISSUE_TEMPLATE/img-tag-refactor-on-website.md +++ b/.github/ISSUE_TEMPLATE/img-tag-refactor-on-website.md @@ -11,7 +11,7 @@ assignees: '' ### Prerequisite 1. Be a member of Hack for LA. (There are no fees to join.) If you have not joined yet, please follow the steps on our [Getting Started page](https://www.hackforla.org/getting-started) and attend an onboarding session. -2. Before you claim or start working on an issue, please make sure you have read our [How to Contribute to Hack for LA Guide](https://github.com/hackforla/website/blob/7f0c132c96f71230b8935759e1f8711ccb340c0f/CONTRIBUTING.md). +2. Before you claim or start working on an issue, please make sure you have read our [How to Contribute to Hack for LA Guide](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md). ### Overview We want to change an img HTML tag ending with a slash () to an img tag without an ending slash () so that the codebase is consistent with how we use img HTML tags. diff --git a/.github/ISSUE_TEMPLATE/post-an-open-role.md b/.github/ISSUE_TEMPLATE/post-an-open-role.md new file mode 100644 index 0000000000..d0edf58d09 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/post-an-open-role.md @@ -0,0 +1,12 @@ +--- +name: Post an open role +about: Recruit volunteers for specific open roles template +title: 'HfLA Website: Open Role for: [Replace with NAME OF ROLE]' +labels: 'Complexity: Small, role missing' +assignees: '' + +--- + +![image](https://user-images.githubusercontent.com/37763229/162992303-b0fae60e-1886-45ce-93c1-d1a27a909327.png) + +[INSERT DRAFT FROM THE Recruit volunteers for team open roles issue] diff --git a/.github/ISSUE_TEMPLATE/pre-work-template---design.md b/.github/ISSUE_TEMPLATE/pre-work-template---design.md index 6e034a3c12..ffd07a5b1c 100644 --- a/.github/ISSUE_TEMPLATE/pre-work-template---design.md +++ b/.github/ISSUE_TEMPLATE/pre-work-template---design.md @@ -26,7 +26,7 @@ As a new designer on the HfLA website UX team, fill in the following fields as y - [ ] Attend weekly team meetings: - [ ] UX weekly team meeting, Wednesday 2:30 pm PST - [ ] All team meeting (UX, Development, Product), Sunday 10am PST - - [ ] Note regarding weekly team meeting requirements: All website team members are required to attend at least 1 team meeting in a week (held on Wednesdays and Sundays). In case, you are unable in any given week, you should reach out to the design lead. Exceptions to this requirement may be provided on a case-by-case basis. Also, please let the design lead know (through a slack message in the hfla-site channel as well as an @ mention in a comment of the issue that you would be working on) if you are planning to take a week off or a longer vacation. + - [ ] Note regarding weekly team meeting requirements: All website team members are required to attend at least 1 team meeting in a week (held on Wednesdays and Sundays). In case, you are unable in any given week, you should reach out to the design lead. Exceptions to this requirement may be provided on a case-by-case basis. Also, please let the design lead know (through a Slack message in the hfla-site channel as well as an @ mention in a comment of the issue that you would be working on) if you are planning to take a week off or a longer vacation. - [ ] Review [Design_Short Term Goals, Plan, and Tasks](https://docs.google.com/document/d/1FxwgdnWBbbQ8Pi3tspnukZTWwXtqnRXfNkNhVMEloY0/edit) - [ ] Review the [Start Here](https://www.figma.com/file/0RRPy1Ph7HafI3qOITg0Mr/Hack-for-LA-Website?node-id=8561%3A72465) and [Design System](https://www.figma.com/file/0RRPy1Ph7HafI3qOITg0Mr/Hack-for-LA-Website?node-id=3464%3A3) pages in Figma - [ ] Review the [prioritized Backlog to see what Design Issues](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+design%22#column-7198257) are available (this will not be the complete list, but will give you some talking points for your conversation with your lead). @@ -63,7 +63,7 @@ Progress through issues with increasing complexity in the following order: - First, you should post the question as a comment on your assigned issue, so it can be easily referred to in the next bullet points - Then, add the issue to the "Design Weekly Meeting Agenda" column of the Project Board so that it can be addressed in the next design meeting - You may also add the label "Status: Help Wanted" so other designers can see it and potentially help answer your question -- Lastly, you can post your question in the hfla slack channel and link the issue you're working on, so other volunteers can see and respond +- Lastly, you can post your question in the hfla Slack channel and link the issue you're working on, so other volunteers can see and respond ### Resources/Instructions - [GitHub Project Board - Hack for LA ](https://github.com/hackforla/website/projects/7) diff --git a/.github/ISSUE_TEMPLATE/pre-work-template--dev.md b/.github/ISSUE_TEMPLATE/pre-work-template--dev.md index 4f3c4f8185..0be137a345 100644 --- a/.github/ISSUE_TEMPLATE/pre-work-template--dev.md +++ b/.github/ISSUE_TEMPLATE/pre-work-template--dev.md @@ -24,7 +24,6 @@ As a new developer on the HfLA website team, fill in the following fields as you - [ ] Add yourself to the #hfla-site and #hfla-site-pr Slack channels - [ ] To find contact information for the merge team members and technical leads, please take a look at our [Meet the Team wiki page](https://github.com/hackforla/website/wiki/Meet-the-Team) - [ ] Add yourself to the [team roster](https://docs.google.com/spreadsheets/d/11u71eT-rZTKvVP8Yj_1rKxf2V45GCaFz4AXA7tS_asM/edit#gid=0) -- [ ] After you have finished adding yourself to the roster, let a merge team member or a technical lead know you have added yourself to the roster and would like to be added to the `website-write` and `website` teams on GitHub - [ ] Self Assign this issue (gear in right side panel) - [ ] Add the "role: front end" or "role: back end" or both label(s) to this issue and remove the "role missing" label (gear in right side panel) - [ ] Add this issue to the Project Board under the Projects section (gear in right side panel) @@ -34,8 +33,8 @@ As a new developer on the HfLA website team, fill in the following fields as you - [ ] (Optional) Office Hours, Thursdays 7-8pm PST - [ ] All team meeting (UX, Development, Product), Sunday 10am-12pm PST - [ ] Note: There are no meetings on the 1st-7th of every month. -- [ ] Note regarding weekly team meeting requirements: All website team members are required to attend at least 1 team meeting in a week (held on Tuesdays, Thursdays and Sundays). In case, you are unable in any given week, you should reach out to the tech leadership team. Exceptions to this requirement may be provided on a case-by-case basis. Also, please let the tech leadership team know (through a slack message in the hfla-site channel as well as an @ mention in a comment of the issue that you would be working on) if you are planning to take a week off or a longer vacation. -- [ ] Complete steps 1.1 - 1.6 in [Part 1: Setting up the development environment within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#part-1-setting-up-the-development-environment) +- [ ] Note regarding weekly team meeting requirements: All website team members are required to attend at least 1 team meeting in a week (held on Tuesdays, Thursdays and Sundays). In case, you are unable in any given week, you should reach out to the tech leadership team. Exceptions to this requirement may be provided on a case-by-case basis. Also, please let the tech leadership team know (through a Slack message in the hfla-site channel as well as an @ mention in a comment of the issue that you would be working on) if you are planning to take a week off or a longer vacation. +- [ ] Complete steps 1.1 - 1.7 in [Part 1: Setting up the development environment within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#part-1-setting-up-the-development-environment) - [ ] OPTIONAL: If you run into any issues, use [4.1 How do I ask for help within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#41-what-do-i-do-if-i-need-help) as a visual example to get a hold of our [HfLA website leadership team](https://github.com/hackforla/website/projects/7#card-69730135). That way we can help you resolve any set up issues immediately. - [ ] Read section 2.1 - 2.4 in [Part 2: How the Website team works with GitHub issues within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#part-2-how-the-website-team-works-with-github-issues) - [ ] Follow the steps in section [2.3 Where can I find GitHub issues to work on?](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#23-where-can-i-find-github-issues-to-work-on) to assign yourself your first issue under the Project Board's Prioritized Backlog column and use [2.7 Working on a Issue within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#27-working-on-an-issue) to start working on your issue @@ -83,7 +82,7 @@ Progress through issues in the [prioritized backlog](https://github.com/hackforl ### What should I do if I have a question about an issue I'm working on, and I haven't gotten a response yet? - First, you should post the question or blocker as a comment on your assigned issue, so it can be easily referred to in the next bullet points. - Then, add the label "Status: Help Wanted" so other developers can see it and potentially help answer your question. In addition, you will still need to post a Slack message or bring it up in meeting so we know you need help; see below for how to do that. -- Also, you can post your question on the hfla-site slack channel and link the issue you're working on, so other developers can see and respond. +- Also, you can post your question on the hfla-site Slack channel and link the issue you're working on, so other developers can see and respond. - Lastly, you can add the issue to the "Development team meeting discussion items" column of the Project Board so that it can be addressed in the next development meeting. Please bring it during the meeting that you need help. ### Resources/Instructions diff --git a/.github/ISSUE_TEMPLATE/project-profile-card-review-and-update.yml b/.github/ISSUE_TEMPLATE/project-profile-card-review-and-update.yml index 3b479cf939..73c3c63573 100644 --- a/.github/ISSUE_TEMPLATE/project-profile-card-review-and-update.yml +++ b/.github/ISSUE_TEMPLATE/project-profile-card-review-and-update.yml @@ -36,6 +36,7 @@ body: - "LA TDM Calculator" - "Lucky Parking" - "Open Community Survey" + - "Tech Work Experience" - "VRMS" - "Write for All" - "Youth Justice Nav" @@ -93,6 +94,7 @@ body: - "shared-housing-project.md" - "spare.md" - "tdm-calculator.md" + - "tech-work-experience.md" - "undebate.md" - "vrms.md" - "website.md" @@ -217,6 +219,20 @@ body: id: github-link attributes: label: GitHub Link + + - type: dropdown + id: additional-github-repos-yes-no + attributes: + label: "Do you have any additional (other than your primary) GitHub repositories that your volunteers make issues or PRs against?" + options: + - "YES" + - "NO" + validations: + required: true + - type: textarea + id: additional-github-repos + attributes: + label: "If yes, list the repo URLs here" - type: dropdown id: update-slack-link-yes-no diff --git a/.github/ISSUE_TEMPLATE/project-profile-leader-updates---add.md b/.github/ISSUE_TEMPLATE/project-profile-leader-updates---add.md new file mode 100644 index 0000000000..5b447ea2ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/project-profile-leader-updates---add.md @@ -0,0 +1,44 @@ +--- +name: Project Profile leader updates - Add +about: This template is for website team only to ADD a single volunteer +title: 'Update Project Profile: [Project Name] Add [Name of Volunteer]' +labels: 'good first issue, P-Feature: Project Info and Page, role: back end/devOps, + role: front end, size: 0.25pt, time sensitive' +assignees: '' + +--- + +### Prerequisites +1. Be a member of Hack for LA. (There are no fees to join.) If you have not joined yet, please follow the steps on our [Getting Started](https://www.hackforla.org/getting-started) page and attend an onboarding session. +2. You have already read our [How to Contribute to Hack for LA Guide](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md). + +### Overview +We need to keep project information up to date so that visitors to the website can find accurate information. + +### Action Items +- [ ] In your IDE, open the `_projects/[Insert filename].md` file. +- [ ] Observe the existing syntax of the front matter block [^1] in the file. +- [ ] Find the `leadership` variable and add the following profile. +``` + - name: [Insert leadership member's name] + github-handle: [Insert GitHub handle] + role: [Insert role] + links: + slack: https://hackforla.slack.com/team/[Insert Slack member ID] + github: https://github.com/[Insert GitHub handle] + picture: https://avatars.githubusercontent.com/[Insert GitHub handle] +``` +- [ ] Verify the changes by viewing the following in your local environment and include before and after screenshots with your pull request: + - [ ] [Insert name of project] page [^2] +- [ ] Once your pull request is merged, go to the initiating ER [^3] + - [ ] Check off this issue under the _Dependency_ section + - [ ] If all the issues in the _Dependency_ section are checked off, move initiating ER [^3] to **Questions / In Review** column and uncheck the **Dependency label**. + -
+ Click here to see how to uncheck the Dependency label + +
+ +### Resources/Instructions +[^1]: [Info about the front matter block](https://jekyllrb.com/docs/front-matter/) +[^2]: Project detailed info page URL: [Insert project specific page URL here] +[^3]: initiating ER: #[Insert ER number] diff --git a/.github/ISSUE_TEMPLATE/project-profile-leader-updates---remove.md b/.github/ISSUE_TEMPLATE/project-profile-leader-updates---remove.md new file mode 100644 index 0000000000..40fdb49789 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/project-profile-leader-updates---remove.md @@ -0,0 +1,38 @@ +--- +name: Project Profile leader updates - Remove +about: 'This template is for website team only to REMOVE a single volunteer ' +title: 'Update Project Profile: [Name of Project] Remove [Name of Volunteer]' +labels: 'good first issue, P-Feature: Project Info and Page, role: back end/devOps, + role: front end, size: 0.25pt, time sensitive' +assignees: '' + +--- + +### Prerequisites +1. Be a member of Hack for LA. (There are no fees to join.) If you have not joined yet, please follow the steps on our [Getting Started](https://www.hackforla.org/getting-started) page and attend an onboarding session. +2. You have already read our [How to Contribute to Hack for LA Guide](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md). + +### Overview +We need to keep project information up to date so that visitors to the website can find accurate information. + +### Action Items +- [ ] In your IDE, open the `_projects/[Insert filename].md` file. +- [ ] Observe the existing syntax of the front matter block [^1] in the file. +- [ ] Find the `leadership` variable and remove the following: +``` +[Insert the lines of code to remove the specified leadership member] +``` +- [ ] Verify the changes by viewing the following in your local environment and include before and after screenshots with your pull request: + - [ ] [Insert name of project] page [^2] +- [ ] Once your pull request is merged, go to the initiating ER [^3] + - [ ] Check off this issue under the _Dependency_ section + - [ ] If all the issues in the _Dependency_ section are checked off, move initiating ER [^3] to **Questions / In Review** column and uncheck the **Dependency label**. + -
+ Click here to see how to uncheck the Dependency label + +
+ +### Resources/Instructions +[^1]: [Info about the front matter block](https://jekyllrb.com/docs/front-matter/) +[^2]: Project detailed info page URL: [Insert project specific page URL here] +[^3]: initiating ER: #[Insert ER number] diff --git a/.github/ISSUE_TEMPLATE/skills-issue--developer.md b/.github/ISSUE_TEMPLATE/skills-issue--developer.md new file mode 100644 index 0000000000..183d9cd2aa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/skills-issue--developer.md @@ -0,0 +1,659 @@ +--- +name: 'Skills Issue: Developer' +about: Guides all developers through their time on the website team +title: 'Skills Issue: Developer: [replace brackets with your name]' +labels: 'Complexity: Prework, Feature: Board/GitHub Maintenance, role missing, size: + 3pt' +assignees: '' + +--- + +### Prerequisite +We are looking forward to having you on our team. Please make sure to attend the general Hack for LA onboarding to get the process started https://meetup.com/hackforla/events. + +### Overview +As a developer on the Website team this issue will be your companion and a place to track your progress with the path we have set out for you. + +### Special Notes +1. This issue will stay open for as long as you are on the Website team. Use it as a place to indicate that you have completed a level as well as get instructions on how to progress. +2. Usually we don't want you to have more than one issue assigned to you at a time, this issue is the exception, because it is instructions on how to work on other issues. Do not close this issue until you leave the team (please see to do items associated with leaving professionally). +3. The action items listed below should mostly be worked on in a sequential order. However, you don't have to wait on one if you can proceed with the others. For instance, you don't have to wait for attending a weekly meeting before setting up your dev environment. +4. During the general Hack for LA onboarding, you will be directed to fill out a form that will add you to the Website team Google Drive and GitHub teams, and then you will add yourself to the roster. If you have not done that yet, you will not be able to do the action items in section 1. +5. The template that this issue is made from is a work in progress. We will be updating it, and possibly updating your issue. It works through section 17. But after that it's still a work in progress. If any of the links don't work, please leave a note in the comments on this issue https://github.com/hackforla/website/issues/4944, and we will get you an update. + + +### Action Items +#### Table of Contents +Sections + 1 - [Joining the website team](#section-1) + 2 - [Team Meetings (Options and Requirements)](#section-2) + 3 - [Development Environment Setup](#section-3) + 4 - [First GitHub Issue (GFI)](#section-4) + 5 - [Weekly Updates](#section-5) + 6 - [1st Pull Request](#section-6) + 7 - [Additional reading 1](#section-7) + 8 - [2nd good first issue](#section-8) + 9 - [Pull Request Reviews - GFI](#section-9) +10 - [Additional reading 2](#section-10) +11 - [Small Issue](#section-11) +12 - [Pull Request Reviews - Small](#section-12) +13 - [Issue Making - Level 1 (GFI & Small)](#section-13) +14 - [Medium Issue](#section-14) +14.1 [Issue Making - Level 2 (Medium)](#section-14.1) +15 - [Pull Request Reviews - Medium](#section-15) +16 - [Issue Making - Level 2 (GFI)](#section-16) +17 - [Merge Team Skills Review](#section-17) +[FAQ](#section-faq) +[Resources](#resources) + + +#### 1 - JOINING THE WEBSITE TEAM. +- [ ] Add yourself to the [#hfla-site](https://hackforla.slack.com/archives/C4UM52W93) and [#hfla-site-pr](https://hackforla.slack.com/archives/C025ERFDM4Y) Slack channels +- [ ] Self assign this issue (gear in right side panel). + - [ ] If there are no gears in the right side panel of this issue (next to Assignees, Labels, Projects, Milestone, Development): + - [ ] check to see if you are logged in to GitHub (if you are not logged in you will see a sign in button on the top right of this browser tab). + - if you are not logged in + - [ ] log in and try to self assign again. If that does not work, continue with the instructions below. + - if you are logged in + - [ ] contact a merge team member or technical lead on the hfla-site Slack channel with the following message + ``` + Hi. I don't see the gear on my issue, here are my details: + - issue: # + - GitHub handle: + - date onboarded: + - row on roster: + ``` + - [ ] add the following text to a comment on this issue + ``` + I don't have access, I have messaged the merge team / technical lead in the hfla-site Slack channel. + + [return to section 1](#section-1) + ``` +- [ ] Register for Zoom meetings using the forms in the [Register for Meetings slide](https://docs.google.com/presentation/d/1jg2UusQkY4APKf6Jn-q-pRDYZrae1DzI5cH76GXsMKQ/edit?pli=1#slide=id.g26ea7b29f52_0_14) +- [ ] Add the `role: front end` or `role: back end/devOps` or both label(s) to this issue and remove the `role missing` label (gear in right side panel) +- [ ] Add this issue to the Project Board under the Projects section (gear in right side panel) +- [ ] Sign up for a [Figma](https://Figma.com) account + +- [ ] Fill out the [INTAKE Self Test](#Intake_Skills_List) so that we can help you find issues that will match where you need to fill in. +- [ ] Post the following message in a comment below on this issue and then answer it. + ``` + ### 1 - JOINING THE WEBSITE TEAM update + >How many hours did it take you to finish this step? + + A: + + [return to section 1](#section-1) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + + +#### 2 - TEAM MEETINGS (OPTIONS AND REQUIREMENTS) +- [ ] Attend weekly team meetings: + - [ ] Developer (front-end/back-end) weekly team meeting, Tuesdays 7-8pm Pacific + - [ ] (Optional) Office Hours, Thursdays 7-8pm Pacific + - [ ] All team meeting (UX, Development, Product), Sunday 10am-12pm Pacific +- [ ] Note: The meetings on the 1st-7th of every month are planning meetings for leads and merge team. You are welcome to observe but we don't provide team member support. +- [ ] Note regarding weekly team meeting requirements: All website team members are required to attend at least 1 team meeting in a week (held on Tuesdays, Thursdays and Sundays). In case, you are unable in any given week, you should reach out to the tech leadership team. Exceptions to this requirement may be provided on a case-by-case basis. Also, please let the tech leadership team know through a Slack message in the #hfla-site Slack channel as well as an @ mention in a comment of the issue that you would be working on, if you are planning to take a week off or a longer vacation. +- [ ] Post the following message in a comment below on this issue and then answer it. + ``` + ### 2 - TEAM MEETINGS update + >which meetings did you register for + - [ ] Developer (front-end/back-end) + - [ ] (Optional) Office Hours + - [ ] All team meeting + >When did you attend your first team meeting? + + A: + + [return to section 2](#section-2) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 3 - DEVELOPMENT ENVIRONMENT SETUP +- [ ] Complete steps 1.1 - 1.7 in [Part 1: Setting up the development environment within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#part-1-setting-up-the-development-environment) + - [ ] OPTIONAL: If you run into any issues, use [4.1 How do I ask for help within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#41-what-do-i-do-if-i-need-help) + + - [ ] If you have never setup your development environment before, please update your [Ongoing Skills List](#Ongoing_Skills_List) to check off "Setting up your local environment from a contributing file" +- [ ] Post the following message in a comment below on this issue and then answer it. While keeping in mind that this is just to get feedback on how long it took you to get to this point. There is no right or wrong answers. There is no judgement. It is ok if you take a long time or if you do it really fast or at any pace. Getting your dev environment setup will be easier for some people because they might already have some experience or items installed on their computer and you may not. This is an important step, be patient with yourself and your computer but keep on it till you get it done. + ``` + ### 3 - GETTING YOUR DEVELOPMENT ENVIRONMENT SETUP update + >How many hours did it take you to finish this step? + + A: + + [return to section 3](#section-3) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 4 - FINDING AND ASSIGNING YOUR FIRST GITHUB ISSUE (GFI) +- [ ] Read section 2.1 - 2.2 in [Part 2: How the Website team works with GitHub issues within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#part-2-how-the-website-team-works-with-github-issues) +- [ ] Take the first issue from this prefiltered view of the project board (status: prioritized backlog, good first issues = [dev: GFI](https://github.com/orgs/hackforla/projects/86/views/2)) + - [ ] Follow the steps in section [2.4 Claiming an Issue](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#24-claiming-an-issue) to assign yourself your first issue. + - [ ] Move your issue from the Project Board's "Prioritized Backlog" column to the "In progress (actively working)" column and use [2.7 Working on a Issue within Contributing.md](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#27-working-on-an-issue) to start working on your issue + - [ ] Read [2.6 What to do when you need to stop mid issue](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#26-what-to-do-when-you-need-to-stop-mid-issue) +- Once you self assign an issue, an automation will post a welcome message in a comment giving you additional guidance to manage your issue (includes how to provide estimates and progress reports there). + - [ ] On assignment, you will be prompted to estimate Availability and ETA. + >Availability for this week: + > + >My estimated ETA for completing this issue: + + Once you have done that on your good first issue, check this box, above, on this issue to let us know you have completed that task and understand how to do it in future. + - If you have any questions about estimating the issue you choose, please add them to the issue, put the issue in the "Questions/ In Review" column, and add the labels `ready for dev lead` and `Status: Help Wanted` +- [ ] Post the following message in a comment below on this issue and then answer it. + ``` + ### 4 - FINDING AND ASSIGNING YOUR FIRST GITHUB ISSUE update + >How many hours did it take you to finish this step? + + A: + + [return to section 4](#section-4) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 5 - GIVING WEEKLY UPDATES ON YOUR DEVELOPMENT ISSUES +- [ ] Progress Reports: Copy the below and put it in the issue once you have been assigned to the issue at least 5 days (we check weekly on Fridays), or sooner if you have something to report. If you finish this issue before 5 days are reached, Yeah!!, do it on your next issue. **This update should be done every week for every issue that you are assigned to**. The checkbox here is meant for us to see if you understood the instructions when you end up doing your first weekly progress update. + ``` + Provide Update + 1. Progress + 2. Blockers + 3. Availability + 4. ETA + ``` +- [ ] Post the following message in a comment below on this issue and then answer it. + ``` + ### 5 - GIVING WEEKLY UPDATES ON YOUR DEVELOPMENT ISSUES update + >on what issue did you give your first weekly update? + + - # + + [return to section 5](#section-5) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 6 - SUBMITTING YOUR FIRST PULL REQUEST +- [ ] Read sections 3.1.a - 3.1.c in [3.1 How to make a pull request](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md#31-how-to-make-a-pull-request) to learn more about how to make a pull request (PR) for the issue that you are working on and how to make changes to your PR if changes are requested by the reviewer + - Confirm you understand the following: + - [ ] Please work on only one issue at a time and wait until your pull request is merged before picking up another issue. + - [ ] Please keep an eye on your PR, if someone leaves you a comment asking for a change, please respond in a timely way. +- [ ] Once your pull request has been accepted, post the following message in a comment below on this issue and then answer it. + ``` + ### 6 - PULL REQUESTS update + >What is the number of your first merged pull request? + - # + >Did you receive any reviews that required you to change anything on your PR? + - [ ] no + - [ ] yes (if yes, describe what you learned) + + Comments: + + [return to section 6](#section-6) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 7 - ADVANCED READING TO READY YOU FOR LARGER MORE COMPLEX ISSUES +- [ ] Read the [Start Here - Developers](https://www.figma.com/file/0RRPy1Ph7HafI3qOITg0Mr/Hack-for-LA-Website?node-id=8583%3A0) in Figma +- [ ] Go familiarize yourself with the [Hack for LA Design System page in Figma](https://www.figma.com/file/0RRPy1Ph7HafI3qOITg0Mr/Hack-for-LA-Website?node-id=3464%3A3) (where you can see components and their SCSS classes) +- [ ] Post the following message in a comment below on this issue and then answer it. + ``` + ### 7 - ADVANCED READING TO READY YOU FOR LARGER MORE COMPLEX ISSUES update + >How many hours did it take you to finish this step? + + A: + >Do you have any questions about what you read? + - [ ] yes, I had questions, and I left comments in the appropriate issues [WE NEED TO UPDATE THOSE TWO RESOURCES TO HAVE LINKS TO ISSUES WHERE PEOPLE CAN PUT QUESTIONS AND MOVE THE ISSUES TO THE QUESTIONS/REVIEW COLUMN] + - [ ] no, I did not have any questions + + [return to section 7](#section-7) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 8 - MOVE ON TO 2ND GOOD FIRST ISSUE (AKA, IT GETS EASIER AND DID YOU BRANCH CORRECTLY?) +- Do another good first issue (two per person total). We have you do another simple issue because this we want you to + - see the difference once you have successful setup your dev environment + - see how each PR gets easier to do with repetition + - make sure you know how to branch properly (most problems show up in the second commit) +- [ ] Take the first issue from this prefiltered view of the project board (status: prioritized backlog, good first issues = [dev: GFI](https://github.com/orgs/hackforla/projects/86/views/2)) +- [ ] Submit your PR +- Once your pull request has been accepted + + - [ ] Update your [Ongoing Skills List](#Ongoing_Skills_List) to check off "GitHub branching" & "Pull Requests" + - [ ] post the following message in a comment below on this issue and then answer it. + ``` + ### 8 - MOVE ON TO 2ND GOOD FIRST ISSUE update + >What is the number of your 2nd merged pull request? + - # + >Did you receive any reviews that required you to change anything on your PR? + - [ ] no + - [ ] yes (if yes, describe what you learned) + + Comments: + + [return to section 8](#section-8) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 9 - GOOD FIRST ISSUE (GFI) PULL REQUEST REVIEWS +Now that you have two merged `good first issue` PRs, you are eligible to review [good first issue PRs, Review Required](https://github.com/hackforla/website/pulls?q=is%3Apr+is%3Aopen+label%3A%22good+first+issue%22+review%3Arequired) from other people who are following in the same journey path as you. + +See [How to review Pull Requests](https://github.com/hackforla/website/wiki/How-to-review-pull-requests) guide will teach you how to review pull requests. + +Please review 5 `good first issue` PRs. Each PR requires at least two reviews, so by reviewing 5 good first issue PRs you are repaying the effort that others did for you (provided 4 reviews for your 2 good first issues) plus 1 extra review to help us all make up the deficit for people who submit a PR but don't get this far. +- [ ] reviewed 1st `good first issue` pr +- [ ] reviewed 2nd `good first issue` pr +- [ ] reviewed 3rd `good first issue` pr +- [ ] reviewed 4th `good first issue` pr +- [ ] reviewed 5th `good first issue` pr + - [ ] After each `good first issue` PR that your review, please paste the following text in a comment below + ``` + ### 9 - PULL REQUEST REVIEWS - GFI - Update + I have reviewed a `good first issue` PR # + >Did you catch anything? + + - [ ] yes + - [ ] no + >If you did't catch anything, did anyone else who reviewed it after you, catch anything? + + - [ ] no + - [ ] yes + + >if yes, describe what you learned: + + A: + + [return to section 9](#section-9) + ``` + + - [ ] Once all 5 good first PRs have been merged, check of the box for "good first issue" under "Reviewed other people's Pull Requests" on the [Ongoing Skills List](#Ongoing_Skills_List) + - [ ] If there are no `good first issue` PRs to review right now, paste this comment instead and check back later. You can also go onto section 10. + ``` + ### 9 - PULL REQUEST REVIEWS - GFI - Update + There are currently no `good first issue` PRs to review, but ill check back later. + + [return to section 9](#section-9) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 10 - UNDERSTAND HOW TO PROGRESS THROUGH ISSUES IN THE PRIORITIZED BACKLOG AND ON ISSUE MAKING AND TEMPERATURE CHECK +Congrats on making it this far. Issues get more complicated from here, either they include more changes, or have several files to change or you have to research something that we are unsure how to do, or there is complicated logic that needs writing or rewriting. Each issue size that you take on will guide you to a more complicated level in sequence, and you can see from the labels and overviews what they are about. + +Its important that you try to work on issues that fill in gaps in your knowledge (see the self tests for a reminder about what to look for). +- [INTAKE Self Test](#Intake_Skills_List) +- [ONGOING Skills List](#Ongoing_Skills_List) + +So keep going, the fun stuff is about to start. + +Having said that, we are also going to have you take on some issue making (surprise! There is no issue making fairy, only volunteers like you that created issues for the people that come after them). Pay attention to how the issues you have already worked on are constructed and how they change as they go up the ladder. That way when we start you on the issue making portion of the team work, you will know what you are shooting for when its your time to make issues. + +Also, we want you on the Merge team. This will ensure you are a competent developer and an awesome collaborative contributor to any team you join in the future. + +- [ ] Let us know that you have re-reviewed your issues, have read the above and are continuing on the team + ``` + ### 10 - UNDERSTAND HOW TO PROGRESS THROUGH ISSUES IN THE PRIORITIZED BACKLOG AND ON ISSUE MAKING update + >Up to now we have just been getting you ready. Now the fun starts. Are you continuing? + - [ ] I'm so ready, bring it on (continuing) + - [ ] I am worn out from the setup and the good first issues but still game (continuing) + - [ ] I won't be continuing, (please let us know why and close this issue) + + Comments: + + [return to section 10](#section-10) + ``` + +[THIS WHOLE THING COULD BE MOVED TO A WIKI PAGE THAT EXPLAINS THE VALUE TO THEIR CAREER AND HAVE A TLDR HERE] + +[**⇧** Table of Contents](#table-of=contents) + + +#### 11 - MOVING ON TO A SMALL ISSUE +- [ ] Assign yourself a small issue, for the role you have indicated, from this prefiltered view of the project board (status: prioritized backlog, small = [dev: small](https://github.com/orgs/hackforla/projects/86/views/3)) +- [ ] Follow the instructions the bot adds as comments on the issue +- [ ] Submit your PR +- [ ] Once your pull request has been merged post the following message in a comment below on this issue and then answer it: + ``` + ### 11 - SMALL update + >What is the number of your small merged pull request? + - # + >Did you receive any reviews that required you to change anything on your PR? + - [ ] no + - [ ] yes (if yes, describe what you learned) + + Comments: + + [return to section 11](#section-11) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 12 - PULL REQUEST REVIEWS - SMALL +Now that you have your small PR merged, you are eligible to review [small PRs, Review Required](https://github.com/hackforla/website/pulls?q=is%3Aopen+is%3Apr+label%3A%22Complexity%3A+Small%22+review%3Arequired) from other people who are following in the same journey path as you. + +Please review 3 `small` PRs. Each PR requires at least two reviews, so by reviewing 3 small PRs you are repaying the effort that others did for you (provided 2 reviews for your 1 small issue PR) plus 1 extra review to help us all make up the deficit for people who submit small PRs and then drop off the team. +- [ ] reviewed 1st `small` pr +- [ ] reviewed 2nd `small` pr +- [ ] reviewed 3rd `small` pr + - [ ] When you have reviewed a `small` PR, please paste the following text in a comment below + ``` + ### 12 - PULL REQUEST REVIEWS - Small - Update + I have reviewed a `small` PR # + + >Did you catch anything? + + - [ ] yes + - [ ] no + >If you did't catch anything, did anyone else who reviewed it after you, catch anything? + + - [ ] no + - [ ] yes + + >if yes, describe what you learned: + + A: + + [return to section 12](#section-12) + ``` + + - [ ] Once all 3 good first PRs have been merged, check off the box for "small" under "Reviewed other people's Pull Requests" on the [Ongoing Skills List](#Ongoing_Skills_List) + - [ ] If there are no `small` PRs to review right now, paste this comment instead and check back later. You can also go onto section 13. + ``` + ### 12 - PULL REQUEST REVIEWS - Small - Update + There are currently no `small` PRs to review, but i'll check back later. + + [return to section 12](#section-12) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 13 - GET EXPERIENCE MAKING ISSUES - LEVEL 1 (GFI & Small) +Creating issues from templates will give you experience on how issues +- are constructed +- are queued up for review +- are queued up for approval +- are prioritized (milestones) +- and appear in the prioritzed backlog + +and like the good first and small issues you have already done, they are perscritive enough to do with no prior experience issue making. +- [ ] Take the first issue from this prefiltered view of the project board (status: ERs and epics that are ready to be turned into issues, good first & small = [IM: 1 + extra filters](https://github.com/orgs/hackforla/projects/86/views/8?filterQuery=status%3A%22ERs+and+epics+that+are+ready+to+be+turned+into+issues%22+label%3A%22Issue+Making%3A+Level+1%22+label%3A%22good+first+issue%22%2C%22complexity%3A+small%22)) +- [ ] Assign yourself +- [ ] Move the issue to the in progress column +- [ ] Follow the instructions in the issue +- [ ] create the issue(s) it calls for. These new issues will end up in the new issue approval column with the label `ready for merge team` +- Once the ER or Epic has been accepted by the Merge team and closed and the issue(s) you created have been moved into the prioritized backlog + - [ ] Post the following message in a comment below on this issue and then answer it. + ``` + ### 13 - GET EXPERIENCE MAKING ISSUES - LEVEL 1 (GFI & Small) update + >Which EPIC or ER did you work on (provide the issue number) + + # + + >How many hours did it take you to make the issue(s)? + + Number of hours: + + >Did you find anything required clarification or anything we could improve about the instructions? + + Suggestions for improvement: + + [return to section 13](#section-13) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 14 - MOVING ON TO A MEDIUM ISSUE +- [ ] Take the first issue from this prefiltered view of the project board (status: prioritized backlog, medium issues = [dev: medium](https://github.com/orgs/hackforla/projects/86/views/4)) + - [ ] If there are no medium size issues in the prioritized backlog column, skip the rest of this section and go to [Section 14.1](#section-14.1) + - [ ] If there is medium size issue in the prioritized backlog column + - [ ] Assign yourself a medium for the role you have indicated (front/backend or both) + - [ ] Follow the instructions the bot adds as comments on the issue + - [ ] Submit your PR + - [ ] Once your pull request has been merged, post the following message in a comment below on this issue and then answer it + ``` + ### 14 - MEDIUM update + >What is the number of your medium merged pull request? + - # + >Did you receive any reviews that required you to change anything on your PR? + - [ ] no + - [ ] yes (if yes, describe what you learned) + + Comments: + + [return to section 14](#section-14) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 14.1 MAKE A MEDIUM ISSUE FROM AN ER OR EPIC +Only work on this section if you needed a medium issue and one is not available from the prioritized backlog +- [ ] add the label `needs issue: medium` to this issue, so that we can notify you when new medium size issues are released +- [ ] add the following comment to this issue + ``` + There are no medium issues right now. Please let me know if one becomes available. + + [return to section 14](#section-14.1) + ``` +- [ ] Take the first issue from this prefiltered view of the project board (status: ERs and epics that are ready to be turned into issues, medium = [IM: Level 1 + Complexity: Medium](https://github.com/orgs/hackforla/projects/86/views/8?filterQuery=status%3A%22ERs+and+epics+that+are+ready+to+be+turned+into+issues%22+label%3A%22Issue+Making%3A+Level+1%22+label%3A%22complexity%3A+medium%22) + - If you find any results in the column + - [ ] assign yourself to the first issue in that column + - [ ] move the ER or EPIC to the in progress column + - [ ] create the issue(s) it calls for. These new issues will end up in the new issue approval column with the label `ready for merge team` + - [ ] once you have made the issues and added the labels, move the issue making ER or Epic issue into the questions column + - [ ] add a comment, letting the merge team know that you have made the issues (include a link to each of the new issues) + - [ ] add the label `ready for merge team` + - [ ] there will likely be some back and forth with the merge team, until your issue(s)s are approved and a `ready for prioritization` label is added. When the new issue(s) are approved, the issue making issue will be closed and you are welcome to move onto the next checkbox +- [ ] Check this prefiltered view of the project board (status: prioritized backlog, medium issues = [dev: medium](https://github.com/orgs/hackforla/projects/86/views/4) + - If there still is no medium issue to work in the Priortized Backlog column. + - [ ] Leave the following message as a comment one of the Medium issues you just created and when the issue is prioritized we will assign the issue to you if there are no other medium issues you have picked up. + ``` + - I created this issue, so I could have a medium issue to work on. Please assign to me once approved. My Skills Issue is # + ``` + - once you get assigned, + - [ ] hide the comment below that says "There are no medium issues right now. Please let me know if one becomes available." + - [ ] remove from this issue, the label `needs issue: medium` + - [ ] circle back to [Section 14](#section-14) and check off the first 4 boxes, and continue from there. + +[**⇧** Table of Contents](#table-of=contents) + + +#### 15 - PULL REQUEST REVIEWS - Medium +Now that you have your medium PR merged, you are eligible to review [medium PRs, Review Required](https://github.com/hackforla/website/pulls?q=is%3Aopen+is%3Apr+label%3A%22Complexity%3A+Medium%22+review%3Arequired) from other people who are following in the same journey path as you. + +Please review 3 `medium` PRs. Each PR requires at least two reviews, so by reviewing 3 medium PRs you are repaying the effort that others did for you (provided 2 reviews for your 1 medium issue PR) plus 1 extra review to help us all make up the deficit for people who submit medium PRs and then drop off the team. +- [ ] reviewed 1st `medium` pr +- [ ] reviewed 2nd `medium` pr +- [ ] reviewed 3rd `medium` pr + - [ ] When you have reviewed a `medium` PR, please paste the following text in a comment below + ``` + ### 15 - PULL REQUEST REVIEWS - Medium - Update + I have reviewed a `medium` PR # + + >Did you catch anything? + + - [ ] yes + - [ ] no + >If you did't catch anything, did anyone else who reviewed it after you, catch anything? + + - [ ] no + - [ ] yes + + >if yes, describe what you learned: + + A: + + [return to section 15](#section-15) + ``` + - [ ] If there are no `medium` PRs to review right now, paste this comment instead and check back later. You can also go onto section 16. + ``` + ### 15 - PULL REQUEST REVIEWS - Medium - Update + There are currently no `medium` PRs to review, but i'll check back later. + + [return to section 15](#section-15) + ``` + +[**⇧** Table of Contents](#table-of=contents) + + +#### 16 - ISSUE MAKING - LEVEL 2, GFI +- [ ] Take the first issue from this prefiltered view of the project board (status: ERs and epics that are ready to be turned into issues, good first issue = [IM: Level 2 + good first issue](https://github.com/orgs/hackforla/projects/86/views/9?filterQuery=status%3A%22ERs+and+epics+that+are+ready+to+be+turned+into+issues%22+label%3A%22Issue+Making%3A+Level+2%22+label%3A%22good+first+issue%22) + - If you find any results in the make issues column + - [ ] assign yourself to the first issue in that column + - [ ] move the ER or EPIC to the in progress column + - [ ] create the issue(s) it calls for. These new issues will end up in the new issue approval column with the label `ready for merge team` + - [ ] once you have made the issues and added the labels, move the issue making ER or Epic issue into the questions column + - [ ] add a comment, letting the merge team know that you have made the issues (include a link to each of the new issues) + - [ ] add the label `ready for merge team` + - [ ] there might be some back and forth with the merge team, until your issues are ready to be prioritized. When it is, the issue making issue will be closed and you are welcome to move onto the next checkbox + +[**⇧** Table of Contents](#table-of=contents) + + +#### 17 - MERGE TEAM SKILLS REVIEW +We want everyone who joins this team to get onto the merge team so that you can get experience running meetings and office hours, mentoring, creating sufficent workflow for the team, escalations, and ultimately being responsible for final approval and merging of pull requests made by team members on lower sections. At this point we will check to see if you are ready to join the merge team, or what your next steps are to get you closer to ready. + +- [ ] When you get to this point, please paste the following message into a comment below +``` +I have finished sections 1-16 and am ready to have my activity reviewed by the merge team + + [return to section 17](#section-17) +``` +- [ ] Copy the link your comment into the #hfla-site Slack channel + +[**⇧** Table of Contents](#table-of=contents) + + +#### FAQ section + +
Are there exceptions to which size issues I work on? + + - Medium (you can work on one medium issue, but only one at a timeone per person, with some exceptions, see below) + - Large (you can work on more than one large issue, but only one at a time) +- The reasons for this progression are: + - The issues start out as being prescriptive and become less so as you gain more experience by working through increasingly complex issues. + - We are trying to teach you the team methodology through the issues themselves. + - It ensures you understand what we expect and the quality of contributions. + - You can work on back-to-back small issues if it meets the following criteria: + - You are learning something new and need to work on an issue of a lesser complexity + - Since we have a limited number of these, you must get approval from lead or pm + - You can work on a second medium issue if it meets the following criteria: + - You are learning something new and need to work on an issue of a lesser complexity + - Since we have a limited number of these, you must get approval from lead or pm +
+ +
What should I do if I have a question about an issue I'm working on, and I haven't gotten a response yet? + +- First, you should post the question or blocker as a comment on your assigned issue, so it can be easily referred to in the next bullet points. +- Then, add the label `Status: Help Wanted` so other developers can see it and potentially help answer your question. In addition, you will still need to post a Slack message or bring it up in meeting so we know you need help; see below for how to do that. +- Also, you can post your question on the hfla-site Slack channel and link the issue you're working on, so other developers can see and respond. +- Lastly, you can add the issue to the "Development team meeting discussion items" "Questions/In Review" column of the Project Board so that it can be addressed in the next development meeting. Please bring it during the meeting that you need help. +
+ +
If you need to take some time off from the team + +- For this Skills Issue, please do the following: + - Copy and customize this response, and leave it in a comment on this issue + ``` + I need to take some time off from the team. I believe I will be back on [Replace with DATE YOU WILL BE BACK] + ``` + - Apply the label `away on hold`. + - Move your Skills Issue to the `Questions / In Review` column. +- In the [roster](https://docs.google.com/spreadsheets/d/11u71eT-rZTKvVP8Yj_1rKxf2V45GCaFz4AXA7tS_asM/edit?gid=0#gid=0), find the line with your information on it and fill in your info for the following columns: + - Find Column N / "Hiatus". Put `TRUE` in that column. + - Find column O / "If on Hiatus, return date (YY-MM-DD)". Fill in your expected return date in YY-MM-DD format. +- In addition, if you are assigned to an open issue (other than your Skills Issue), do the following for that issue: + - If you have done some work on the issue, please write thorough documentation in a comment in that issue so that the issue can be handed off to another person, who can pick up working where you left off based on your notes. + - Apply a `ready for prioritization` label. + - Move it to the 'New Issue Approval` column. + - Then, unassign yourself from that issue. +
+ +[**⇧** Table of Contents](#table-of=contents) + +### Resources/Instructions +- [Contributing.md - Hack for LA](https://github.com/hackforla/website/blob/gh-pages/CONTRIBUTING.md) +- [GitHub Project Board - Hack for LA](https://github.com/orgs/hackforla/projects/86) +- [Figma - Hack for LA](https://www.figma.com/file/0RRPy1Ph7HafI3qOITg0Mr/Hack-for-LA-Website) +- [Google Drive - Hack for LA website team](https://drive.google.com/drive/folders/1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT?usp=sharing) +- [Agenda / Notes - Dev Team Tuesday meeting](https://github.com/hackforla/website/issues/2010) +- [Agenda / Notes - All Team meeting](https://github.com/hackforla/website/issues/2027) +- [How to review Pull Requests](https://github.com/hackforla/website/wiki/How-to-review-pull-requests) +- To find contact information for the merge team members and technical leads, please take a look at our [Meet the Team wiki page](https://github.com/hackforla/website/wiki/Meet-the-Team) + +[**⇧** Table of Contents](#table-of=contents) + +--- + + +### Skills List - INTAKE +Skills List, self test on Intake, fill out when you join the team, don't update + + Front End + - [ ] Setting up your local environment from a contributing file + - [ ] GitHub branching + - [ ] Pull Requests + + Back End + - [ ] API requests + - [ ] Cron Job Scripting + - [ ] CRUD operations + + All Developers + - [ ] Reviewed other people's Pull Requests + - [ ] Resolved Merge Conflicts + - [ ] Written documentation for other Developers (Architecture, etc.) + - [ ] Mentored other developers + +Return to +[section 1](#section-1-intake-self-test) +[section 10](#section-10) + + + + +### Skills List - ONGOING +Skills List, update as you do work on this team + + Front End + - [ ] Setting up your local environment from a contributing file ([section 3](#section-3-ongoing-self-test)) + - [ ] GitHub branching (done in section 8) + - [ ] Pull Requests ([section 8](#section-8-ongoing-self-test)) + + Back End + - [ ] API requests + - Cron Job Scripting + - [ ] edit GitHub Action + - [ ] write GitHub Action + - [ ] CRUD operations + + All Developers + - Reviewed other people's Pull Requests + - [ ] good first issue ([section 9](#section-9-ongoing-self-test)) + - [ ] smal ([section 12](#section-12-ongoing-self-test)) + - [ ] medium + - [ ] large + - [ ] x-large + - [ ] Resolved Merge Conflicts + - [ ] Written documentation for other Developers (Architecture, etc.) + - [ ] Mentored other developers + + +[**⇧** Table of Contents](#table-of=contents) diff --git a/.github/ISSUE_TEMPLATE/spell-check-audit.md b/.github/ISSUE_TEMPLATE/spell-check-audit.md index 9da3dd4c36..90b217af08 100644 --- a/.github/ISSUE_TEMPLATE/spell-check-audit.md +++ b/.github/ISSUE_TEMPLATE/spell-check-audit.md @@ -2,8 +2,8 @@ name: Spell check audit web page about: For checking spelling on a code file that contains text displayed on the website title: Run VS Code Spell Checker on [INSERT FILE HERE] -labels: 'Complexity: Small, Feature: Administrative, ready for dev lead, role: back - end/devOps, role: front end, size: 0.5pt' +labels: 'Complexity: Small, feature: spelling, ready for merge team, role: back end/devOps, + role: front end, size: 0.5pt' assignees: '' --- @@ -18,7 +18,7 @@ We need to audit HfLA codebase files for spelling errors using the Code Spell Ch - [ ] Locate the file in column A ("File") of the "Page Audit" sheet. In the column labeled "Result Summary", select the appropriate option: `No errors` or `At least one error`. - [ ] If at least one error was reported, copy/paste each cSpell message into a separate row in the `Results` sheet - [ ] In each new row, select the appropriate value: `misspelling` or `false positive` from the "Result type" column. A false positive is a term that is not a misspelling but is not recognized by the spell checker because it is a technical term, abbreviation, acronym, URL or proper noun (name of a person, place or organization). -- [ ] Move this issue to the Questions/In Review column and apply the label `ready for dev lead` +- [ ] Move this issue to the Questions/In Review column and apply the label `ready for merge team` ### Merge Team - [ ] After this issue is closed, release the dependency on this issue in #5248 diff --git a/.github/ISSUE_TEMPLATE/suggest-a-feature-or-new-content-for-hackforla-org.md b/.github/ISSUE_TEMPLATE/suggest-a-feature-or-new-content-for-hackforla-org.md index aea6a035d0..c30a50366c 100644 --- a/.github/ISSUE_TEMPLATE/suggest-a-feature-or-new-content-for-hackforla-org.md +++ b/.github/ISSUE_TEMPLATE/suggest-a-feature-or-new-content-for-hackforla-org.md @@ -1,7 +1,7 @@ --- name: Suggest a feature or new content for HackforLA.org about: Describe this issue template's purpose here. -title: '' +title: Suggest a feature or new content for the HackforLA.org website labels: 'Complexity: Missing, enhancement, Feature Missing, role missing, size: missing' assignees: '' diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 87d9011483..c5d463a730 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,9 @@ updates: directory: "/github-actions/trigger-schedule/github-data" schedule: interval: "daily" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-patch"] - package-ecosystem: "github-actions" # Workflow files stored in the @@ -12,3 +15,8 @@ updates: directory: "/" schedule: interval: "daily" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-patch"] + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0b6ac723c6..7dc7652e5f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,18 +1,53 @@ + Fixes #replace_this_text_with_the_issue_number ### What changes did you make? - - - - - - + + - + - + - ### Why did you make the changes (we will use this info to test)? - - - - - - + + - + - + - -### Screenshots of Proposed Changes Of The Website (if any, please do not screen shot code changes) - - +

CodeQL Alerts

+ + +After the PR has been submitted and the resulting GitHub actions/checks have been completed, developers should check the PR for CodeQL alert annotations. + + +
Check the PR's comments. If present on your PR, the CodeQL alert looks similar as shown + +![Screenshot 2024-10-28 154514](https://github.com/user-attachments/assets/ea66c586-c14c-45fd-8705-1c116224e704) + + +
+ +Please let us know that you have checked for CodeQL alerts. **Please do not dismiss alerts.** +- [ ] I have checked this PR for CodeQL alerts and none were found. +- [ ] I found CodeQL alert(s), and (select one): + - [ ] I have resolved the CodeQL alert(s) as noted + - [ ] I believe the CodeQL alert(s) is a false positive (Merge Team will evaluate) + - [ ] I have followed the Instructions below, but I am still stuck (Merge Team will evaluate) + +
Instructions for resolving CodeQL alerts + +If CodeQL alert/annotations appear, refer to [How to Resolve CodeQL alerts](https://github.com/hackforla/website/issues/6463#issuecomment-2002573270). + +In general, CodeQL alerts should be resolved prior to PR reviews and merging + +
+ +### Screenshots of Proposed Changes To The Website (if any, please do not include screenshots of code changes) +
Visuals before changes are applied diff --git a/.github/workflows/codeql-create-issues.yml b/.github/workflows/codeql-create-issues.yml new file mode 100644 index 0000000000..56778c3841 --- /dev/null +++ b/.github/workflows/codeql-create-issues.yml @@ -0,0 +1,51 @@ +# This workflow generates new issues for CodeQL alerts if they do not exist +# It must be manually triggered +name: "CodeQL Create Issues" + +on: + workflow_dispatch: + +jobs: + codql-scan-job: + uses: ./.github/workflows/codeql-scan-job.yml + + codeql-create-issues-job: + needs: codql-scan-job + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Fetch Alerts + - name: Fetch Alerts + id: fetch-alerts + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const script = require('./github-actions/trigger-issue/create-codeql-issues/fetch-alerts.js'); + const fetchAlerts = script({ g: github, c: context }); + return fetchAlerts + + # Check Existing Issues + - name: Check Existing Issues + id: check-existing-issues + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const script = require('./github-actions/trigger-issue/create-codeql-issues/check-existing-issues.js'); + const alerts = ${{ steps.fetch-alerts.outputs.result }}; + const checkExistingIssues = script({ g: github, c: context, alerts}); + return checkExistingIssues + + # Create New Issues + - name: Create New Issues + id: create-new-issues + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HACKFORLA_ADMIN_TOKEN }} + script: | + const script = require('./github-actions/trigger-issue/create-codeql-issues/create-new-issues.js'); + const alertIds = ${{ steps.check-existing-issues.outputs.result }}; + const newIssues = script({ g: github, c: context, alertIds}); diff --git a/.github/workflows/codeql-scan-job.yml b/.github/workflows/codeql-scan-job.yml new file mode 100644 index 0000000000..1b5823692c --- /dev/null +++ b/.github/workflows/codeql-scan-job.yml @@ -0,0 +1,77 @@ + +# This workflow called by codeql.yml and codeql-create-issues.yml +# It is a reusable workflow +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Scan Job" +# workflow_call enables this workflow to be called from other workflows +on: + workflow_call: + +jobs: + analyze: + name: Analyze + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + queries: security-and-quality + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" + + \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 85c3f1127d..6b55f7efca 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,78 +1,17 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" +# This is the main codeql.yml file which scans for CodeQL alerts. +# Most of the code is in .github/workflows/codeql-scan-job.yml +name: "CodeQL Scan" on: push: - branches: [ "gh-pages" ] + branches: [ 'gh-pages' ] pull_request: # The branches below must be a subset of the branches above - branches: [ "gh-pages" ] + branches: [ 'gh-pages' ] schedule: - cron: '30 5 * * 5' + workflow_dispatch: jobs: - analyze: - name: Analyze - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'javascript' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] - # Use only 'java' to analyze code written in Java, Kotlin or both - # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - queries: security-and-quality - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" \ No newline at end of file + codeql-scan-job: + uses: ./.github/workflows/codeql-scan-job.yml \ No newline at end of file diff --git a/.github/workflows/issue-trigger.yml b/.github/workflows/issue-trigger.yml index 55bfd9af08..8212998243 100644 --- a/.github/workflows/issue-trigger.yml +++ b/.github/workflows/issue-trigger.yml @@ -1,29 +1,13 @@ name: Issue Trigger on: issues: - types: [opened, transferred, assigned] + types: [opened, transferred, assigned, labeled, unlabeled] jobs: - # Adds newly created issues onto project board in the default column 'New Issue Approval' - # unless overridden when issue has "LA website bot" in title, then 'Questions / In Review' - Add-Issue-To-Project-Board: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'issues' && github.event.action == 'opened' }} - env: - COLUMN_NAME: ${{ contains(github.event.issue.title, 'Hack for LA website bot') && 'Questions / In Review' || 'New Issue Approval' }} - steps: - - name: Add issue to project board - id: add-issue-project-board - uses: alex-page/github-project-automation-plus@v0.9.0 - with: - project: Project Board - column: ${{ env.COLUMN_NAME }} - repo-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - + # Adds missing labels to newly-created or transferred issues Add-Missing-Labels-To-Issues: runs-on: ubuntu-latest - # Only trigger this action when an issue is newly created - if: ${{ github.event_name == 'issues' && (github.event.action == 'opened' || github.event.action == 'transferred')}} + if: ${{ github.event.action == 'opened' || github.event.action == 'transferred' }} steps: - uses: actions/checkout@v4 # Check if the issue has required labels @@ -31,12 +15,13 @@ jobs: id: check-labels uses: actions/github-script@v7 with: + github-token: ${{ secrets.HACKFORLA_GRAPHQL_TOKEN }} script: | const script = require('./github-actions/trigger-issue/add-missing-labels-to-issues/check-labels.js') const checkLabels = script({g: github, c: context}) return checkLabels - #Checks which teams the user is on + # Checks if user is on the 'website-write' team - uses: tspascoal/get-user-teams-membership@v3 id: checkUserMember with: @@ -45,9 +30,8 @@ jobs: team: 'website-write' GITHUB_TOKEN: ${{ secrets.TEAMS }} - # Checks if user is on the website-write-team + # Posts comment only if user is team member (based on the previous action's result) - if: ${{ steps.checkUserMember.outputs.isTeamMember == 'true' }} - # Post comment based on the previous action's results name: Post Comment uses: actions/github-script@v7 id: post-comment @@ -58,15 +42,13 @@ jobs: script({g: github, c:context}, results) - #Asking for preliminary update when issue is assigned + # Asks for preliminary update when issue is assigned Ask-For-Preliminary-update: runs-on: ubuntu-latest - #Triggers when the issue is newly assigned - if: ${{ github.event_name == 'issues' && github.event.action == 'assigned'}} + if: ${{ github.event.action == 'assigned' }} steps: - uses: actions/checkout@v4 - - # Check if the issue has the required roles + # Checks if the issue has the required roles (front end, back end/devOps, design, or user research) - name: Check Labels Prelim uses: actions/github-script@v7 id: check-labels-prelim @@ -76,12 +58,40 @@ jobs: const checklabels = script({g: github, c: context}) return checklabels - # Post the comment based on the result of the previous step + # Posts the comment based on the result of the previous step - name: Post assigning issue comment id: assigned-comment uses: actions/github-script@v7 with: + github-token: ${{ secrets.HACKFORLA_GRAPHQL_TOKEN }} script: | const results = ${{ steps.check-labels-prelim.outputs.result }} const script = require('./github-actions/trigger-issue/add-preliminary-comment/preliminary-update-comment.js') - script({g: github, c:context},results) + script({g: github, c:context}, results) + + + # The following steps only apply to issues with `Feature: Feature Branch` label + # Note: These steps will be unnecessary and should be removed once Feature Branch goes live + Add-Feature-Branch-Comment: + runs-on: ubuntu-latest + if: "${{ github.event.action == 'labeled' && github.event.label.name == 'Feature: Feature Branch' }}" + steps: + - uses: actions/checkout@v4 + - name: Add feature branch comment + uses: actions/github-script@v7 + with: + script: | + const script = require('./github-actions/trigger-issue/feature-branch-comment/add-feature-branch-comment.js') + script({g: github, c: context}) + + Hide-Feature-Branch-Comment: + runs-on: ubuntu-latest + if: "${{ github.event.action == 'unlabeled' && github.event.label.name == 'Feature: Feature Branch' }}" + steps: + - uses: actions/checkout@v4 + - name: Hide feature branch comment + uses: actions/github-script@v7 + with: + script: | + const script = require('./github-actions/trigger-issue/feature-branch-comment/hide-feature-branch-comment.js') + script({g: github, c: context}) diff --git a/.github/workflows/lint-scss.yml b/.github/workflows/lint-scss.yml index 0f1078cdd9..cb75a682fd 100644 --- a/.github/workflows/lint-scss.yml +++ b/.github/workflows/lint-scss.yml @@ -19,7 +19,7 @@ jobs: fetch-depth: 0 - name: Lint SCSS - uses: github/super-linter@v5.0.0 + uses: github/super-linter@v4.8.1 env: VALIDATE_ALL_CODEBASE: false DEFAULT_BRANCH: gh-pages diff --git a/.github/workflows/move-closed-issues.yaml b/.github/workflows/move-closed-issues.yaml index 134552068c..08379f5f93 100644 --- a/.github/workflows/move-closed-issues.yaml +++ b/.github/workflows/move-closed-issues.yaml @@ -3,22 +3,31 @@ on: issues: types: - closed + jobs: - move-closed-issue: + Move-Closed-Issues: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + + # 1: Sort closed issues based on labels - name: Sort Closed Issues by Label uses: actions/github-script@v7 id: sort-closed-issues with: script: | - const script = require('./github-actions/move-closed-issues/sort-closed-issues.js') - const sortIssues = script({context}) - return sortIssues + const script = require('./github-actions/move-closed-issues/sort-closed-issues.js'); + const sortIssues = script({context}); + return sortIssues; result-encoding: string - - uses: alex-page/github-project-automation-plus@v0.9.0 + + # 2: Move closed issues + - name: Move Closed Issue + uses: actions/github-script@v7 + id: move-closed-issue with: - project: Project Board - column: ${{ steps.sort-closed-issues.outputs.result }} - repo-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} + github-token: ${{ secrets.HACKFORLA_GRAPHQL_TOKEN }} + script: | + const results = '${{ steps.sort-closed-issues.outputs.result }}'; + const script = require('./github-actions/move-closed-issues/move-closed-issues.js'); + script({github, context}, results); diff --git a/.github/workflows/pr-instructions.yml b/.github/workflows/pr-instructions.yml index 04e9fc687d..15a585de64 100644 --- a/.github/workflows/pr-instructions.yml +++ b/.github/workflows/pr-instructions.yml @@ -19,8 +19,9 @@ jobs: with: script: | const script = require('./github-actions/pr-instructions/create-instruction.js') - const instruction = script({g: github, c: context}) - return JSON.stringify({ instruction: instruction, issueNum: context.payload.number }) + return script({g: github, c: context}).then((instruction) => { + return JSON.stringify({ instruction: instruction, issueNum: context.payload.number }) + }) # Create an artifact with the message - name: Create Artifacts diff --git a/.github/workflows/pr-verification.yml b/.github/workflows/pr-verification.yml new file mode 100644 index 0000000000..dec2521ad0 --- /dev/null +++ b/.github/workflows/pr-verification.yml @@ -0,0 +1,16 @@ +name: Pull Request Verification +on: + pull_request_target: + types: [opened] + +jobs: + Check-Team-Membership: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HACKFORLA_ADMIN_TOKEN }} + script: | + const verifyPR = require('./github-actions/trigger-pr-target/verify-pr.js'); + verifyPR({github, context}); diff --git a/.github/workflows/pull-request-trigger.yml b/.github/workflows/pull-request-trigger.yml index 3a11ba65fc..dddc019dcb 100644 --- a/.github/workflows/pull-request-trigger.yml +++ b/.github/workflows/pull-request-trigger.yml @@ -1,67 +1,22 @@ name: Pull Request Trigger on: - pull_request_target: - types: [opened, closed] + pull_request: + types: [opened, edited] branches: - 'gh-pages' jobs: - # Run an echo to confirm that the action was triggered - Hello-World: + Check-For-Linked-Issue: runs-on: ubuntu-latest + if: ${{ github.event.action == 'opened' || github.event.action == 'edited' }} steps: - - run: echo "🍺 This job was automatically triggered by a ${{ github.event_name }} event." + - name: Checkout repository + uses: actions/checkout@v4 - - # Moves newly opened PRs onto Project Board in column 'PR Needs review...' - Move-New-PRs-To-Project-Board: - runs-on: ubuntu-latest - if: ${{ github.event.action == 'opened' }} - steps: - - name: Move Opened PR to Project Board - uses: alex-page/github-project-automation-plus@v0.9.0 - with: - project: Project Board - column: 'PR Needs review (Automated Column, do not place items here manually)' - repo-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - - - # Gathers merged PRs from every location and moves to column 'test-approved-by-reviewer...' - Gather-Merged-PRs: - runs-on: ubuntu-latest - if: ${{ github.event.pull_request.merged == true }} - steps: - - name: Gather Merged PRs - uses: alex-page/github-project-automation-plus@v0.9.0 - with: - project: Project Board - column: 'test-approved-by-reviewer (Automated Column, do not place items here manually)' - repo-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - - - # Deletes merged PRs from column 'test-approved-by-reviewer...' after 'needs: Gather-Merged-PRs' - Delete-Merged-PRs: - needs: Gather-Merged-PRs - runs-on: ubuntu-latest - if: ${{ github.event.pull_request.merged == true }} - steps: - - name: Delete Merged PRs - uses: alex-page/github-project-automation-plus@v0.9.0 - with: - project: Project Board - column: 'test-approved-by-reviewer (Automated Column, do not place items here manually)' - repo-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - action: delete - - # Removes PRs that are closed and not merged - Delete-Closed-And-Unmerged-PRs: - runs-on: ubuntu-latest - if: ${{ github.event.pull_request.merged == false && github.event.action == 'closed' }} - steps: - - name: Delete Closed and Unmerged PRs - uses: alex-page/github-project-automation-plus@v0.9.0 + - name: Check for keyword and issue number + id: check-for-keyword + uses: actions/github-script@v7 with: - project: Project Board - column: 'PR Needs review (Automated Column, do not place items here manually)' - repo-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - action: delete \ No newline at end of file + script: | + const script = require('./github-actions/trigger-pr/check-linked-issue.js') + script({g: github, c: context}) diff --git a/.github/workflows/schedule-daily-1100.yml b/.github/workflows/schedule-daily-1100.yml index aca12334c2..fb13d4c664 100644 --- a/.github/workflows/schedule-daily-1100.yml +++ b/.github/workflows/schedule-daily-1100.yml @@ -4,7 +4,7 @@ name: Schedule Daily 1100 on: schedule: - cron: '0 11 * * *' - + workflow_dispatch: jobs: github_data: runs-on: ubuntu-latest @@ -28,7 +28,7 @@ jobs: - name: Auto Commit - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: # Optional glob pattern of files which should be added to the commit file_pattern: _data/external/github-data.json diff --git a/.github/workflows/schedule-fri-0700.yml b/.github/workflows/schedule-fri-0700.yml index 3df0c6fe1f..f991252395 100644 --- a/.github/workflows/schedule-fri-0700.yml +++ b/.github/workflows/schedule-fri-0700.yml @@ -1,19 +1,20 @@ name: Schedule Friday 0700 +# This action runs at 7:00 UTC/ 0:00 PDT (midnight) every Friday, except during July and December. on: schedule: - - cron: '0 7 * * 5' + - cron: '0 7 * 1-6,8-11 5' + workflow_dispatch: jobs: Add-Update-Label-to-Issues-Weekly: runs-on: ubuntu-latest + if: github.repository == 'hackforla/website' steps: - uses: actions/checkout@v4 - uses: actions/github-script@v7 - env: - IN_PROGRESS_COLUMN_ID: ${{ secrets.IN_PROGRESS_COLUMN_ID }} with: + github-token: ${{ secrets.HACKFORLA_GRAPHQL_TOKEN }} script: | - const { IN_PROGRESS_COLUMN_ID } = process.env; const script = require('./github-actions/trigger-schedule/add-update-label-weekly/add-label.js'); - script({ g: github, c: context }, IN_PROGRESS_COLUMN_ID); + script({ g: github, c: context }); diff --git a/.github/workflows/schedule-monthly.yml b/.github/workflows/schedule-monthly.yml index a20df497f1..f00d26323f 100644 --- a/.github/workflows/schedule-monthly.yml +++ b/.github/workflows/schedule-monthly.yml @@ -1,78 +1,56 @@ name: Schedule Monthly -# This action runs at 11:00 UTC/ 3:00 PDT on the first day of every month except January. +# This action runs at 11:00 UTC/ 4:00 PDT on the first day of every month except January and August. on: schedule: - - cron: 0 11 1 2-12 * - workflow_dispatch: + - cron: 0 11 1 2-7,9-12 * jobs: Trim_Contributors: runs-on: ubuntu-latest - if: github.repository == 'hackforla/website' + if: github.repository == 'hackforla/website' steps: - # Checkout repo + # Checkout repo, and provide authorization token for `stefanzweifel/git-auto-commit-action` below - name: Checkout repository uses: actions/checkout@v4 - with: - token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - - # Setup node - - name: Setup node - uses: actions/setup-node@v4 - with: - node-version: 18 - cache: 'npm' - - # Install dependencies to run js file - - name: Install npm dependencies - run: npm install - working-directory: ./github-actions/trigger-schedule/github-data - - # Run js file: checks contributor activity logs, removes two-month inactive members from - # 'website-write' team, then compiles list of one-month inactive members for notification - - name: Trim Members - env: - token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} - run: node github-actions/trigger-schedule/github-data/contributors-data.js - - # Upload artifact file to allow list sharing with next job "Create_New_Issue" - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: trim_job_artifact - path: inactive-Members.json + with: + token: ${{ secrets.HACKFORLA_ADMIN_TOKEN }} - - Create_New_Issue: - needs: Trim_Contributors - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - # Download artifact file from "Trim_Contributors" - - name: Download artifact - id: download-artifact - uses: actions/download-artifact@v4 + # Checks member activity logs for recent and previous contributors + - name: Get Contributors + id: get-contributors + uses: actions/github-script@v7 with: - name: trim_job_artifact - - # Extract and save artifact in usable form for next steps - - name: Extract artifact - id: extract-artifact - run: | - jq -c . inactive-Members.json > out-inactive-Members.json - echo "TRIM_LISTS=$(cat out-inactive-Members.json)" >> $GITHUB_ENV + github-token: ${{ secrets.HACKFORLA_ADMIN_TOKEN }} + script: | + const script = require('./github-actions/trigger-schedule/list-inactive-members/get-contributors-data.js') + const results = script({ g: github, c: context }) + return results - # Creates a new issue in 'hackforla/website' repo with the saved lists - - name: Create new issue + # Trims inactive members from team and notifies idle members + - name: Trim and Notify Members + id: trim-and-notify-members uses: actions/github-script@v7 - id: create-new-issue with: - github-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} + github-token: ${{ secrets.HACKFORLA_ADMIN_TOKEN }} script: | - const artifactContent = process.env.TRIM_LISTS - const script = require('./github-actions/trigger-schedule/list-inactive-members/create-new-issue.js') - script({g: github, c: context}, artifactContent) - + const results = ${{ steps.get-contributors.outputs.result }} + const script = require('./github-actions/trigger-schedule/list-inactive-members/trim-inactive-members.js') + script({ g: github, c: context }, results) + + # Run `git pull` so that branch is current prior to next step + - name: Pull latest changes from gh-pages + run: git pull + + # Commits list of inactive members to repo for using in next step, and in one month + - name: Update Inactive Members JSON + id: update-inactive-members-json + uses: stefanzweifel/git-auto-commit-action@v5.0.1 + with: + # Glob pattern of file which should be added to the commit + file_pattern: github-actions/utils/_data/inactive-members.json + + # Optional commit message and author settings + commit_message: Update Inactive Members JSON + commit_author: GitHub Actions Bot diff --git a/.github/workflows/update-label-directory.yml b/.github/workflows/update-label-directory.yml new file mode 100644 index 0000000000..01f9c3460d --- /dev/null +++ b/.github/workflows/update-label-directory.yml @@ -0,0 +1,50 @@ +# This workflow updates `github-actions/utils/_data/label-directory.json` +# and the Google Sheets doc `Website Labels 'Source of Truth'` at URL below + +name: Update Label Directory + +on: + label: + types: [edited, created, deleted] + +jobs: + Update-Label-Directory: + runs-on: ubuntu-latest + if: github.repository == 'hackforla/website' + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} + + - name: Update label directory + id: update-label-directory + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} + script: | + const script = require('./github-actions/utils/update-label-directory.js') + const labelPacket = script({g: github, c: context}) + return labelPacket + + # NOTE: the the URL below matches the **current deployment URL** of the Apps Script + # associated with the 'Source of Truth'Label spreadsheet and maintained by + # `hackforla-bot@hackforla.org`. (If something is broken, check this link first) + - name: Send POST request to Google Apps Script + env: + label_edits: ${{ steps.update-label-directory.outputs.result }} + run: | + curl -X POST "https://script.google.com/macros/s/AKfycbw_kmDVqQW5J8wXWl1BXvJzALU6k0XYpAc5XJ7inQSyq8_opUuNg4ToBzh3Gf4M5jhw/exec" \ + -H "Content-Type: application/json" \ + -d "$label_edits" + + # Before next step, run `git pull` so that branch is current + - name: Pull latest changes from gh-pages + run: git pull + + - name: Commit changes to JSON Label Directory + uses: stefanzweifel/git-auto-commit-action@v5.0.1 + with: + # Glob pattern of file to commit, and opt. commit message + author + file_pattern: github-actions/utils/_data/label-directory.json + commit_message: Update label directory + commit_author: GitHub Actions Bot diff --git a/.github/workflows/vrms-data.yml b/.github/workflows/vrms-data.yml index e2d4d4462a..5f18e947c7 100644 --- a/.github/workflows/vrms-data.yml +++ b/.github/workflows/vrms-data.yml @@ -21,7 +21,7 @@ jobs: - name: Save vrms_data.json run: curl --retry 7 --fail -o _data/external/vrms_data.json https://www.vrms.io/api/recurringevents - - uses: stefanzweifel/git-auto-commit-action@v5.0.0 + - uses: stefanzweifel/git-auto-commit-action@v5.0.1 with: # Optional glob pattern of files which should be added to the commit file_pattern: _data/external/vrms_data.json diff --git a/.github/workflows/wr-schedule-monthly.yml b/.github/workflows/wr-schedule-monthly.yml index 5192fc8b59..6fe9dea113 100644 --- a/.github/workflows/wr-schedule-monthly.yml +++ b/.github/workflows/wr-schedule-monthly.yml @@ -6,13 +6,29 @@ on: types: [completed] jobs: - On-success: + Create-New-Issue: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - run: echo "The 'Schedule Monthly' workflow succeeded. Continuing." + - uses: actions/checkout@v4 - # If 'Schedule Monthly' was succcesful, retrieve the owner URL + # Creates a new issue in 'hackforla/website' repo with the saved lists + - name: Create new issue + id: create-new-issue + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.HACKFORLA_BOT_PA_TOKEN }} + script: | + const script = require('./github-actions/trigger-schedule/list-inactive-members/create-new-issue.js') + script({g: github, c: context}) + + Close-New-Issue: + needs: Create-New-Issue + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Get owner url id: get-owner-url uses: actions/github-script@v7 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9499d4b4c0..0c3d90546a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ The following is a set of guidelines for contributing to the website repository, **If you need a text editor to work on code, [VS Code](https://code.visualstudio.com/download) is recommended by the team, but feel free to use a text editor of your choice.** -**If you have any other questions about your contributing process, feel free to reach out to the team in the [#hfla-site](https://hackforla.slack.com/archives/C4UM52W93) slack channel.** +**If you have any other questions about your contributing process, feel free to reach out to the team in the [#hfla-site](https://hackforla.slack.com/archives/C4UM52W93) Slack channel.**

## **Table of Contents** @@ -34,11 +34,10 @@ The following is a set of guidelines for contributing to the website repository, - [**2.1 Hack for LA Contributor expectations**](#21-hack-for-la-contributor-expectations) - [**2.2 How Hack for LA organizes issues**](#22-how-hack-for-la-organizes-issues) - [**2.3 Where can I find GitHub issues to work on?**](#23-where-can-i-find-github-issues-to-work-on) - - [**2.3.a Available issues for new members (front end/back end)**](#23a-available-issues-for-new-members-front-endback-end) - - [**2.3.b Available issues for returning members (front end)**](#23b-available-issues-for-returning-members-front-end) - - [**2.3.c Available issues for returning members (back end)**](#23c-available-issues-for-returning-members-back-end) - - [**2.3.d Issues for Hacktoberfest contributors (Front-End/Back-End)**](#23d-issues-for-hacktoberfest-contributors-front-endback-end) - - [**2.3.e What if you see bugs/errors that are not connected to an issue?**](#23e-what-if-you-see-bugserrors-that-are-not-connected-to-an-issue) + - [**2.3.a Available issues for new members**](#23a-available-issues-for-new-members) + - [**2.3.b Available issues for returning members**](#23b-available-issues-for-returning-members) + - [**2.3.c Issues for Hacktoberfest contributors**](#23c-issues-for-hacktoberfest-contributors) + - [**2.3.d What if you see bugs/errors that are not connected to an issue?**](#23d-what-if-you-see-bugserrors-that-are-not-connected-to-an-issue) - [**2.4 Claiming an Issue**](#24-claiming-an-issue) - [**2.4.a Assign & Unassign yourself to this issue**](#24a-assign--unassign-yourself-to-this-issue) - [**i. If you want to to self assign an issue:**](#i-if-you-want-to-to-self-assign-an-issue) @@ -52,8 +51,8 @@ The following is a set of guidelines for contributing to the website repository, - [**2.6.b What to do if you have to stop working mid issue:**](#26b-what-to-do-if-you-have-to-stop-working-mid-issue) - [**2.7 Working on an issue**](#27-working-on-an-issue) - [**2.7.a Working on an issue (1): Verify current branch is `gh-pages`**](#27a-working-on-an-issue-1-verify-current-branch-is-gh-pages) - - [**2.7.b Working on an issue (2): Create a new branch where you will work on your issue**](#27b-working-on-an-issue-2-create-a-new-branch-where-you-will-work-on-your-issue) - - [**i. What if you cannot see your changes locally within Docker?**](#i-what-if-you-cannot-see-your-changes-locally-within-docker) + - [**2.7.b Working on an issue (2): Creating and testing your issue branch**](#27b-working-on-an-issue-2-creating-and-testing-your-issue-branch) + - [**i. A few notes regarding Docker:**](#i-a-few-notes-regarding-docker) - [**2.7.c Working on an issue(3): Prepare your changes to push to your repository**](#27c-working-on-an-issue3-prepare-your-changes-to-push-to-your-repository) - [**i. Prepare repo changes (1): Use the `git add` command to stage your changes.**](#i-prepare-repo-changes-1-use-the-git-add-command-to-stage-your-changes) - [**ii. Prepare repos changes (2): Use the `git status` command to see what files are staged.**](#ii-prepare-repos-changes-2-use-the-git-status-command-to-see-what-files-are-staged) @@ -117,9 +116,9 @@ You can fork the hackforla/website repository by clicking +

Next, a modal may open and request where you want to fork this website repo. Please click on your avatar or your GitHub username

- +

**Note:** It should create a URL that looks like the following -> `https://github.com//website`. @@ -216,7 +215,7 @@ git remote add upstream https://github.com/hackforla/website.git Docker is the recommended approach to quickly getting started with local development. Docker helps create a local/offline version of the hackforla.org website on your computer so you can test out your code before submitting a pull request. -The recommended installation method for your operating system can be found [here](https://docs.docker.com/install/). Feel free to reach out in the [Hack for LA Slack channel](https://hackforla.slack.com/messages/hfla-site/) if you have trouble installing docker on your system +The recommended installation method for your operating system can be found [here](https://docs.docker.com/install/). Feel free to reach out in the [Hack for LA Slack channel](https://hackforla.slack.com/archives/C4UM52W93/) if you have trouble installing docker on your system More on using Docker and the concepts of containerization: @@ -305,23 +304,12 @@ docker-compose up You must use VS Code as your local text editor to install the VS Code extension for spell checking your codebase, Code Spell Checker. -The recommended installation method is to install Code Spell Checker directly from the VS Code text editor, and those instructions can be found [here](https://code.visualstudio.com/learn/get-started/extensions). The extension can also be installed via the VS Code Marketplace website [here](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker). Feel free to reach out in the [Hack for LA Slack channel](https://hackforla.slack.com/messages/hfla-site/) if you have trouble installing the extension in VS Code. - -[Back to Table of Contents](#table-of-contents) - - -*** - -### **1.7 Dev setup (7): Install local codebase spell checker** - -You must use VS Code as your local text editor to install the VS Code extension for spell checking your codebase, Code Spell Checker. - The recommended installation method is to install Code Spell Checker directly from the VS Code text editor, and those instructions can be found [here](https://code.visualstudio.com/learn/get-started/extensions). The extension can also be installed via the VS Code Marketplace website [here](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker). For developers who do not use VS Code, use the corresponding npm package, cspell, and those instructions can be found [here](https://www.npmjs.com/package/cspell). -Feel free to reach out in the [Hack for LA Slack channel](https://hackforla.slack.com/messages/hfla-site/) if you have trouble installing the VS Code extension or the cspell npm package on your system. +Feel free to reach out in the [Hack for LA Slack channel](https://hackforla.slack.com/archives/C4UM52W93/) if you have trouble installing the VS Code extension or the cspell npm package on your system. [Back to Table of Contents](#table-of-contents) *** @@ -330,7 +318,7 @@ For developers who do not use VS Code, use the corresponding npm package, cspell ### **2.1 Hack for LA Contributor expectations** -In order to join [another project within Hack for LA](https://www.hackforla.org/projects/) or work on a `Complexity: Small`/`Complexity: Medium`/`Complexity: Large` label issue within this repo, you need to complete the following: +In order to work on a `Complexity: Small`/`Complexity: Medium`/`Complexity: Large` label issue within this repo, you need to complete the following: 1. `good first issue` * Self-assign an issue with the `good first issue` label. @@ -355,7 +343,21 @@ All website team members are required to attend at least 1 team meeting in a wee All website team members are expected to devote a minimum of 6 hours per week while working on various assignments during their entire tenure at the website team (excluding week offs and vacations). -Also, please let the tech leadership team know (through a slack message in the hfla-site channel as well as an @ mention in a comment of the issue that you would be working on) if you are planning to take a week off or a longer vacation. +Also, please let the tech leadership team know (through a Slack message in the hfla-site channel as well as an @ mention in a comment of the issue that you would be working on) if you are planning to take a week off or a longer vacation. + +Prior to joining [another project within Hack for LA](https://www.hackforla.org/projects/), developers should gain the following experience: +* Setting up your local environment from a CONTRIBUTING file +* Completing the above series of issues at least up to `Complexity: Large` +* Resolving Merge Conflicts +* Reviewing other people's Pull Requests +* Create or improve documentation for other developers +* Mentor other developers +* Create new issues + +In addition, backend engineers should complete issues that provide experience with the following: +* API requests +* Cron Job Scripting +* CRUD operations [Back to Table of Contents](#table-of-contents) *** @@ -383,55 +385,34 @@ And the following **complexity** labels: ### **2.3 Where can I find GitHub issues to work on?** -The best way to view the issues available is our [GitHub Project Board](https://github.com/hackforla/website/projects/7) - -
- Click here to see a Project Board visual -

Our GitHub project board

- -
- -There are only 2 columns that you will be consistently referencing: +The best way to view the issues available is our [GitHub Project Board](https://github.com/orgs/hackforla/projects/86) -1. `Onboarding infos/links` - Some helpful card information examples: - * [Website team meeting times/links card](https://github.com/hackforla/website/projects/7#card-47984166) - * [Website team leadership contact information card](https://github.com/hackforla/website/projects/7#card-69730135) - * Filters to show the project issues by a specific complexity: - * [`role: front end` complexity filters card](https://github.com/hackforla/website/projects/7#card-63001626) - * [`role: back end` complexity filters card](https://github.com/hackforla/website/projects/7#card-65620159) - * [Figma links (ui/ux design team) card](https://github.com/hackforla/website/projects/7#card-38820969) -2. `Prioritized Backlog` - This column contains all the available issues that can be worked on +For the purpose of finding issues to work on, developers should focus exclusively on the `Prioritized Backlog` column, which contains all the available issues that have been approved and prioritized. **Note:** The column is filtered so the first (top) issue has the highest priority and should be worked on next. -#### **2.3.a Available issues for new members (front end/back end)** +#### **2.3.a Available issues for new members** -We recommend you visit the `Prioritized Backlog` column in the filtered Project Board using the following links: [`good first issues` (front end)](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+front+end%22+label%3A%22good+first+issue%22#column-7198257) and [`good first issues` (back end)](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22good+first+issue%22+label%3A%22role%3A+back+end%2Fdevops%22#column-7198257). These links will take you to a filtered Project Board and will only show issues with the `good first issue` label for both front end and back end respectively. +Use the link [`good first issues`](https://github.com/orgs/hackforla/projects/86/views/2) to display "good first issues" (for both front end and back end roles) in the Prioritized Backlog column. **Note:** The column is filtered so the first (top) issue has the highest priority and should be worked on next. -#### **2.3.b Available issues for returning members (front end)** - -* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Small** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22complexity%3A+small%22+label%3A%22role%3A+front+end%22) -* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Medium** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+front+end%22+label%3A%22complexity%3A+medium%22) -* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Large** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+front+end%22+label%3A%22complexity%3A+large%22) +#### **2.3.b Available issues for returning members** -#### **2.3.c Available issues for returning members (back end)** +* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Small** label](https://github.com/orgs/hackforla/projects/86/views/3) +* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Medium** label](https://github.com/orgs/hackforla/projects/86/views/4) +* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Large and XLarge** label](https://github.com/orgs/hackforla/projects/86/views/5) -* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Small** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+back+end%2Fdevops%22+label%3A%22complexity%3A+small%22) -* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Medium** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+back+end%22+label%3A%22complexity%3A+medium%22) -* `Prioritized Backlog` column in the [filtered Project Board - **complexity: Large** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+back+end%2Fdevops%22+label%3A%22complexity%3A+large%22) +#### **2.3.c Issues for Hacktoberfest contributors** -#### **2.3.d Issues for Hacktoberfest contributors (Front-End/Back-End)** - -Please use the `Prioritized Backlog` column in the [filtered Project Board - **Hacktoberfest** label](https://github.com/hackforla/website/projects/7?card_filter_query=label%3A%22role%3A+front+end%22+label%3Ahacktoberfest) +Please use the `Prioritized Backlog` column in the [filtered Project Board - **Hacktoberfest** label](https://github.com/orgs/hackforla/projects/86/views/4?filterQuery=status%3A%22Prioritized+backlog%22+label%3A%22hacktoberfest%22+label%3A%22role%3A+front+end%22+) **Note:** You can only submit a pull request for one (1) issue with the `Hacktoberfest` label. Also leave a comment within the issue you would like to work on. **Note:** If you would like to continue to contribute please join our team. You can find more information on our [Hack for LA Getting Started Page](https://www.hackforla.org/getting-started). -#### **2.3.e What if you see bugs/errors that are not connected to an issue?** +#### **2.3.d What if you see bugs/errors that are not connected to an issue?** -If you see any bugs/errors within the site and there is not an issue for it, please reach out to any of the [Website leadership/merge team](https://github.com/hackforla/website/projects/7#card-69730135) and they will help you create an issue you can resolve. +If you see any bugs/errors within the site and there is not an issue for it, please reach out to any of the [Website leadership/merge team](https://www.hackforla.org/projects/website) and they will help you create an issue you can resolve. [Back to Table of Contents](#table-of-contents) *** @@ -444,7 +425,7 @@ Once you find an issue you want to work on, you need to self-assign to claim it
Click here to see how you assign & unassign yourself to an issue

Assign/Unassign demo

- +
##### **i. If you want to to self assign an issue:** @@ -460,7 +441,7 @@ Once you find an issue you want to work on, you need to self-assign to claim it
Click here to see how to move an issue from the ‘Prioritized Backlog’ to the ‘In progress (actively working)’ & back

Project Board column demo

- +
##### **i. After you claim an issue:** @@ -530,16 +511,16 @@ If you are not currently in the `gh-pages` branch, run the following command to git checkout gh-pages ``` -Update your gh-pages branch with upstream changes +Update your gh-pages branch with upstream changes: -``` +```bash git pull upstream gh-pages ``` [Back to Table of Contents](#table-of-contents) -#### **2.7.b Working on an issue (2): Create a new branch where you will work on your issue** +#### **2.7.b Working on an issue (2): Creating and testing your issue branch** If you have not already done so, run `git checkout gh-pages` to switch the working directory to the `gh-pages` branch and then update `gh-pages` with upstream changes as described above in Section 2.7.a. @@ -565,18 +546,45 @@ We urge developers to be cautious using `git add`. In general it is not advisabl When you've finished working on your issue, follow the steps below to prepare your changes to push to your repository. -##### **i. What if you cannot see your changes locally within Docker?** +##### **i. A few notes regarding Docker:** -If you do not see the changes you applied when you run `docker-compose up`, **do the following**: +- To test your issue branch locally, run the command "docker-compose up" from a terminal window. The website will then be accessible at http://localhost:4000. -1. Stop running your Docker application (if still running). -2. Delete the `_site` directory in the root folder (`website`) -3. Delete the `.jekyll-metadata` file in the root folder (`website`) -4. Finally, restart docker (run `docker-compose up` in the terminal) and you should see your changes. -

+- The Docker Desktop application must be running, otherwise `docker-compose up` will not work +- Docker pulls an image from Dockerhub.com which enables Docker to build the website locally with the same environment used to build the site at GitHub. As the environment and dependencies change, HfLA engineers update the Dockerhub image; however, the image updated at Dockerhub is not automatically downloaded, so it is necessary to periodically check to determine if the local image is outdated, and if so, to pull the updates from Dockerhub. Use this process: + +- In the Docker Desktop application, from the `Images` page, click the Action menu (3 dots) for the image `hackforlaops/ghpages`, select option `View details`. + - In the new Docker Desktop application, select option `View packages and CVEs` instead. + +
+ Click here to see how to view details for a Docker image + + +
+ +- Note the `CREATED` column +
+ Click here to see how to determine when an image was last updated in Docker Desktop + +
+ +- View the details of the "latest" tag from [hackforlaops Dockerhub image tags](https://hub.docker.com/r/hackforlaops/ghpages/tags) and determine when an image was pushed to Docker hub +
+ Click here to see how to determine when an image was pushed to Docker hub + +
+ +- If the "latest" tagged image at Docker hub is more recent than the image in Docker Desktop, use the Docker Desktop Action menu (3 dots) to "pull" down the updated image +
+ Click here to see how to pull image from DockerHub + +
+ +- Note that the next `docker-compose up` will take extra time to recreate the Docker container based on the updated image. - If the above steps did not resolve your issue, run through the first three steps again, but try resetting your browser's cache before restarting docker (you can also try running http://localhost:4000 in another browser). -- If you still do not see your changes after trying these steps, please feel free to reach out to the team in the [#hfla-site](https://hackforla.slack.com/archives/C4UM52W93) slack channel, or bring up your issue in a dev meeting. + +- If you still do not see your changes after trying these steps, please feel free to reach out to the team in the [#hfla-site](https://hackforla.slack.com/archives/C4UM52W93) Slack channel, or bring up your issue in a dev meeting. [Back to Table of Contents](#table-of-contents) @@ -631,18 +639,19 @@ git commit -m “insert message here” #### **2.7.d Working on an issue (4): Pulling from upstream before you push** -**IMPORTANT:** Before you push your local commits to your repository, sync your fork to the main Hack For LA website repository. `git pull upstream` will ensure that your local repository is up-to-date with the main site: - -```bash -git pull upstream -``` -You can also sync your fork directly on GitHub by clicking "Sync Fork" at the right of the screen and then clicking "Update Branch" +**IMPORTANT:** Before you push your local commits to your repository, sync your fork to the main Hack For LA website repository. You can sync your fork directly on GitHub by clicking "Sync Fork" at the right of the screen and then clicking "Update Branch":
Click here to see how to sync the fork on GitHub - +
+Next, bring upstream changes into your topic branch. With your topic branch checked out, run: + +```bash +git pull upstream gh-pages +``` + ##### **i. If there are no changes in the upstream repository** @@ -730,7 +739,9 @@ git merge gh-pages #### **2.7.f Working on an issue (6): Handling SSH authorization errors** -**IMPORTANT:** If you are a windows user then you have to install git bash, but if you are a Mac user you only need to use your terminal. Download git bash for windows here +If you already have an SSH key that connects your computer with your GitHub account, you can skip this section (2.7.f). + +**IMPORTANT:** If you are a Windows user then you have to install Git Bash, but if you are a Mac user you only need to use your terminal. Download Git Bash for Windows here: [Git Bash](https://git-scm.com/downloads) ##### **i. Setting up SSH Keys for Mac** @@ -740,6 +751,10 @@ git merge gh-pages ```bash ls -al ~/.ssh ``` +If the folder ~/.ssh does not exist, create it using +```bash +mkdir ~/.ssh +``` 2. Then enter the text below into your terminal using your github account email address. @@ -769,7 +784,7 @@ pbcopy < ~/.ssh/id_ed25519.pub ##### **ii. Setting up SSH Keys for Windows** -1. You have to set up SSH keys in order to contribute to github remotely. First check if you have any keys set up already. Open Git Bash and run: +1. You have to set up SSH keys in order to contribute to GitHub remotely. First check if you have any keys set up already. Open Git Bash and run: ```bash ls -al ~/.ssh @@ -781,7 +796,7 @@ If the folder ~/.ssh does not exist, create it using mkdir ~/.ssh ``` -2. Then enter the text below into your terminal using your github account email address. +2. Then enter the text below into your terminal using your GitHub account email address. ```bash ssh-keygen -t rsa -b 4096 -C "your_email@example.com" @@ -799,13 +814,13 @@ eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 ``` -5. Finally copy the ssh key to add it to your github account by entering the following command. This copies the contents of the id_ed25519.pub file to your clipboard __Don't copy anything else until after you finish the last step, or else you will have to repeat this step.__ +5. Finally copy the ssh key to add it to your GitHub account by entering the following command. This copies the contents of the id_ed25519.pub file to your clipboard __Don't copy anything else until after you finish the last step, or else you will have to repeat this step.__ ```bash clip < ~/.ssh/id_ed25519.pub ``` -6. Go to your github accounts ssh key settings, and click on the button that says _New SSH key_. In the "Title" field, add a descriptive label for the new key. Paste the key into the form that pops up. Click Add SSH Key +6. Go to your GitHub account's ssh key settings, and click on the button that says _New SSH key_. In the "Title" field, add a descriptive label for the new key. Paste the key into the form that pops up. Click Add SSH Key [Back to Table of Contents](#table-of-contents) *** @@ -835,21 +850,28 @@ git push --set-upstream origin update-give-link-2093 Click here to see pull request markdown template ``` + Fixes #replace_this_text_with_the_issue_number ### What changes did you make? - - - - - - + + - + - + - ### Why did you make the changes (we will use this info to test)? - - - - - - - - ### Screenshots of Proposed Changes Of The Website (if any, please do not screen shot code changes) - - + + - + - + - + + ### Screenshots of Proposed Changes To The Website (if any, please do not include screenshots of code changes) +
Visuals before changes are applied @@ -869,7 +891,7 @@ git push --set-upstream origin update-give-link-2093
Click here to see pull request #2131 example (gif) - +

@@ -919,30 +941,33 @@ In bullet point form, explain the changes you made in order to complete the acti ##### **iv. Complete pull request (4): Include images (if available)** -in the gif example [near the top of this part within the gif of completing pull request #2131](#31-how-to-make-a-pull-request), you will see 2 images get dragged into the text box and added within the `
/` tags like so: +In the dropdown example above [**Click here** to see pull request #2131 example (gif)](#31-how-to-make-a-pull-request), you will see 2 images get dragged into the text box and added within the `
/` tags like so: ``` -### Screenshots of Proposed Changes Of The Website (if any, please do not screen shot code changes) - - +### Screenshots of Proposed Changes Of The Website (if any, please do not include screenshots of code changes) +
-Visuals before changes are applied - -![image](https://user-images.githubusercontent.com/77212035/130176122-aca18c1a-c883-48b3-987d-06342835017c.png) + Visuals before changes are applied + ![image](https://user-images.githubusercontent.com/77212035/130176122-aca18c1a-c883-48b3-987d-06342835017c.png)
-Visuals after changes are applied + Visuals after changes are applied -![image](https://user-images.githubusercontent.com/77212035/130176069-9c1cc306-f930-43a5-9f93-1249466c81dc.png) + ![image](https://user-images.githubusercontent.com/77212035/130176069-9c1cc306-f930-43a5-9f93-1249466c81dc.png)
``` -**Note:** Not all pull requests will have significant changes to our website. **Please do not any screenshots of VSCode** If you do not have the ability to notate changes, please remove the `
//
Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2024-02-14T03:12:46.729Z","startTime":"2024-02-13T02:30:00.729Z","endTime":"2024-02-13T03:00:00.729Z","hours":0.5,"createdDate":"2020-05-09T22:13:25.167Z","updatedDate":"2024-02-13T03:12:46.729Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/87595945272?pwd=bWFzaWdtMWk3WWdjbU00TmhrcnM0dz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb73139509367be7272cf75","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["TBD"],"managedByUsers":[],"_id":"5edeae6cce228b001778face","name":"Community of Practice: DevOps","description":"Operations is a broad area that includes information technology work on devops, infrastructure as code, hosting, pipelines, services, security, practices, and more. ","githubIdentifier":"246449481","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/ops","slackUrl":"https://hackforla.slack.com/archives/CV7QGL66B","googleDriveUrl":"https://drive.google.com/drive/folders/0AAX-8be-yD5JUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-06-08T21:32:28.164Z","__v":0},"date":"2023-08-03T02:15:22.375Z","startTime":"2023-08-01T01:00:00.375Z","endTime":"2023-08-01T02:00:00.375Z","hours":1,"createdDate":"2020-05-09T22:39:53.054Z","updatedDate":"2023-08-01T02:15:22.375Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/84240551835?pwd=cFRGVy9DMnl1QzJPdTlRMlVnV2FvZz09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb736bf509367be7272cf7e","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills (branches, separation of concerns, etc.). We are currently in a redesign phase, using CI/CD in the run up to demoing the new version at Code for America's Summit 2020 in Washington, D.C.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"date":"2023-08-13T21:55:44.544Z","startTime":"2023-08-13T17:00:00.544Z","endTime":"2023-08-13T19:00:00.544Z","hours":2,"createdDate":"2020-05-09T23:03:27.242Z","updatedDate":"2023-08-13T21:55:44.544Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/82177492860?pwd=UGNYdmJXMXgvVmZiSGtETTR4VGV6Zz09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5ebb040346383ef9be2dc2d1","hacknight":"Online","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills (branches, separation of concerns, etc.). We are currently in a redesign phase, using CI/CD in the run up to demoing the new version at Code for America's Summit 2020 in Washington, D.C.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"name":"Dev","eventType":"Team Meeting","description":"","date":"2023-08-15T21:56:00.655Z","startTime":"2023-08-14T02:00:00.655Z","endTime":"2023-08-14T03:00:00.655Z","hours":1,"createdDate":"2020-05-12T20:16:03.981Z","updatedDate":"2023-08-13T21:56:00.654Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/85014559207?pwd=VnM4eDBrTnpVNWgwYUhnNDc3d2oyUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eec3623411acc0017486999","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5eec356c411acc0017486997","name":"Community of Practice: Data Science","description":"","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/website","slackUrl":"","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-06-19T03:47:56.782Z","__v":0},"hacknight":"Westside","name":"All","eventType":"Team Meeting","description":"","date":"2023-09-11T14:28:06.664Z","startTime":"2023-09-06T02:00:00.664Z","endTime":"2023-09-06T03:00:00.664Z","hours":1,"createdDate":"2020-06-19T03:50:59.070Z","updatedDate":"2023-09-05T14:28:06.664Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/83423675645?pwd=anlnM0I3VGgxS3RJTGxCbnQ3Q09aQT09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5ff3d01210cf72445ce37e23","hacknight":"Online","name":"Design","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2023-08-02T17:50:30.452Z","startTime":"2023-07-31T00:00:00.452Z","endTime":"2023-07-31T01:00:00.452Z","hours":1,"createdDate":"2020-05-09T22:02:32.097Z","updatedDate":"2023-07-30T17:50:30.452Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/82255734768?pwd=WnVNU3BPUEZwNGVmYlZuZkN5SlkwZz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"603db433d7b86d36b4f28a63","hacknight":"Online","name":"All","eventType":"Community of Practice","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"603db1fbd7b86d36b4f28a62","name":"Community of Practice: UI/UX","description":"UI/UX Community of Practice","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/UI-UX","slackUrl":"https://app.slack.com/client/T04502KQX/C017ESHSMNG","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"https://us02web.zoom.us/j/89670251875?pwd=NTYySW5yL3YrYTRxcHRpK1V6YWdaQT09","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2023-08-03T02:11:52.643Z","startTime":"2023-08-01T01:00:00.643Z","endTime":"2023-08-01T02:00:00.643Z","hours":1,"createdDate":"2021-03-01T22:38:23.677Z","updatedDate":"2023-08-01T02:11:52.643Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/81630670134?pwd=RTNLRHlBSE1DeXRudkJJMHkzZGlVUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"605773e246b7cd034719d115","hacknight":"Online","name":"All","eventType":"Community of Practice","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605772bb46b7cd034719d114","name":"Community of Practice: Software Engineering","description":"Community of Practice for Software Engineers","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/engineering","slackUrl":"https://hackforla.slack.com/archives/C01CU709SER","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2023-08-17T15:22:52.331Z","startTime":"2023-08-15T01:00:00.331Z","endTime":"2023-08-15T02:00:00.331Z","hours":1,"createdDate":"2021-03-21T22:38:23.677Z","updatedDate":"2023-08-14T15:22:52.331Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/85089810552?pwd=WWw3a0ZMQUdSOWdUcEQ3MWRUMDZEdz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"605d5aba6fb945197a19038d","hacknight":"Online","name":"New Prospective Members","eventType":"Onboarding","description":"Alternating Mon/Tue. Click for schedule","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605d593b6fb945197a19038c","name":"Onboarding","description":"New participant onboarding","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"","slackUrl":"https://hackforla.slack.com/archives/C04S7PNCU","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.meetup.com/hackforla/events","videoConferenceLink":"https://us02web.zoom.us/meeting/register/tZUtdeGvrTMoHtKkRwm7R8Kl8r9TXL73-UY9?_x_zm_rtaid=TNHnsFXoTF2IZlf-TUfrPw.1616083598988.a1e0d0f77cffa24ca0d6e75e25e23695&_x_zm_rhtaid=832","lookingDescription":"","createdDate":"2021-03-25T19:42:22.028Z","__v":0},"date":"2023-09-11T14:16:58.449Z","startTime":"2023-09-09T01:00:00.449Z","endTime":"2023-09-09T04:00:00.449Z","hours":3,"createdDate":"2021-03-25T22:38:23.677Z","updatedDate":"2023-09-08T14:16:58.449Z","__v":0,"videoConferenceLink":"https://zoom.us/"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"605d5bf66fb945197a19038e","hacknight":"Online","name":"New Prospective Members","eventType":"Onboarding","description":"Alternating Mon/Tue. Click for schedule","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605d593b6fb945197a19038c","name":"Onboarding","description":"New participant onboarding","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"","slackUrl":"https://hackforla.slack.com/archives/C04S7PNCU","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.meetup.com/hackforla/events","videoConferenceLink":"https://us02web.zoom.us/meeting/register/tZUtdeGvrTMoHtKkRwm7R8Kl8r9TXL73-UY9?_x_zm_rtaid=TNHnsFXoTF2IZlf-TUfrPw.1616083598988.a1e0d0f77cffa24ca0d6e75e25e23695&_x_zm_rhtaid=832","lookingDescription":"","createdDate":"2021-03-25T19:42:22.028Z","__v":0},"date":"2023-09-12T14:17:29.535Z","startTime":"2023-09-09T01:00:00.535Z","endTime":"2023-09-09T04:00:00.535Z","hours":3,"createdDate":"2021-03-25T22:38:23.677Z","updatedDate":"2023-09-08T14:17:29.535Z","__v":0,"videoConferenceLink":"https://zoom.us/"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6126b9ff9b885ef7d95779e3","hacknight":"Online","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills (branches, separation of concerns, etc.). We are currently in a redesign phase, using CI/CD in the run up to demoing the new version at Code for America's Summit 2020 in Washington, D.C.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"name":"Dev Office Hours","eventType":"Team Meeting","description":"","date":"2023-09-14T14:19:14.051Z","startTime":"2023-09-09T02:00:00.051Z","endTime":"2023-09-09T03:00:00.051Z","hours":1,"createdDate":"2020-05-12T20:16:03.981Z","updatedDate":"2023-09-08T14:19:14.051Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/84412621807?pwd=NTN2eFBtNDg1U05nUWV3UEJuSHpaUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"61b7fc8d71f7e8fa9f644ff8","hacknight":"Online","name":"PM","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2023-09-29T01:54:29.904Z","startTime":"2023-09-29T02:00:00.904Z","endTime":"2023-09-29T03:00:00.904Z","hours":1,"createdDate":"2021-12-13T22:13:25.167Z","updatedDate":"2023-09-29T01:54:29.904Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/88234426474?pwd=bR0kUkJB7BWpUWiaDbLl6bprg0bpKD.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"61b7fd5471f7e8fa9f644ffa","hacknight":"Online","name":"PM/Org","eventType":"Team Meeting","description":"alternating week","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2023-09-29T01:53:57.479Z","startTime":"2023-09-29T01:30:00.479Z","endTime":"2023-09-29T02:00:00.479Z","hours":0.5,"createdDate":"2020-05-09T23:17:12.078Z","updatedDate":"2023-09-29T01:53:57.478Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620998d72720480f934e4365","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"3rd week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2023-11-28T21:44:27.422Z","startTime":"2023-11-29T01:00:00.422Z","endTime":"2023-11-29T02:00:00.422Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2023-11-28T21:44:27.422Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/84729938240?pwd=YlBOd21vbE5PcVhHWTNObk05NlBrUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6209995f2720480f934e4366","hacknight":"Online","name":"UXR","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2023-08-31T02:07:23.572Z","startTime":"2023-08-30T00:00:00.572Z","endTime":"2023-08-30T01:00:00.572Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2023-08-30T02:07:23.572Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/86805459290"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620999902720480f934e4367","hacknight":"Online","name":"Dev","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-02-01T00:52:13.995Z","startTime":"2024-01-30T01:00:00.995Z","endTime":"2024-01-30T02:00:00.995Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2024-01-30T00:52:13.995Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/83647379542?pwd=dZSFVdHEnO5KBZaKlakPz7cp34ga5y.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620999f92720480f934e4368","hacknight":"Online","name":"PM/Org","eventType":"Team Meeting","description":"2nd week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2023-11-15T19:25:24.483Z","startTime":"2023-11-15T18:00:00.483Z","endTime":"2023-11-15T19:00:00.483Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2023-11-15T19:25:24.482Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/81031561471?pwd=KrEnnuposREUCTBVqGaAJaCY9NRK8j.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620bd0be68255664fc376985","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"1st Thursday","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2023-08-17T16:34:19.189Z","startTime":"2023-08-14T01:00:00.189Z","endTime":"2023-08-14T02:00:00.189Z","hours":1,"createdDate":"2020-05-09T22:51:16.674Z","updatedDate":"2023-08-13T16:34:19.189Z","__v":0,"videoConferenceLink":"zoom.com"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"63e1c86c132477014ec310ff","hacknight":"Online","name":"Dev","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2023-09-11T20:15:52.939Z","startTime":"2023-09-08T01:30:00.939Z","endTime":"2023-09-08T03:30:00.939Z","hours":2,"createdDate":"2020-05-09T22:51:16.674Z","updatedDate":"2023-09-07T20:15:52.939Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/89053190313?pwd=cXVCWGpyMlpackJJcEh4Q2xEcDV3dz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"63e58d020f41f6001f62da50","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63e58b5c0f41f6001f62da4f","name":"People Depot","projectStatus":"Active","createdDate":"2023-02-10T00:10:04.622Z","__v":0,"githubUrl":"https://github.com/hackforla/peopledepot/","slackUrl":"https://hackforla.slack.com/archives/C02PTACSRJQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMVDRCjyzDgtUk9PVA","location":"Remote","description":"PeopleDepot aims to provide a single source of truth as the backend infrastructure and data store for Hack for LA projects, including data about people, program areas, and projects. PeopleDepot uses PostgreSQL for its database and Django as the backend data model framework with Django REST Framework for the API layer. PeopleDepot's goal is to serve as a repository of information for other infrastructure projects (e.g., VRMS, Hack for LA Website, Civic Tech Index, Tables, etc).","hflaWebsiteUrl":""},"date":"2023-08-17T15:21:14.805Z","startTime":"2023-08-15T00:00:00.805Z","endTime":"2023-08-15T01:00:00.805Z","hours":1,"createdDate":"2023-02-10T00:17:04.802Z","updatedDate":"2023-08-14T15:21:14.805Z","videoConferenceLink":"https://us02web.zoom.us/j/85496842244?pwd=aTg2Nit1ck1sTlQwQmdwT21WWVdYdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b93ed861655001a9d8a1a","name":"Stakeholder","hacknight":"Online","eventType":"Team Meeting","description":"Every other Tuesday","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2023-08-15T15:03:37.375Z","startTime":"2023-08-14T11:00:00.375Z","endTime":"2023-08-14T12:00:00.375Z","hours":1,"createdDate":"2023-03-10T20:32:39.889Z","updatedDate":"2023-08-14T15:03:37.375Z","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b977ba85983001f385876","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-03-13T17:00:00.114Z","startTime":"2023-03-13T17:00:00.114Z","endTime":"2023-03-13T18:00:00.114Z","hours":1,"createdDate":"2023-03-10T20:47:55.115Z","updatedDate":"2023-03-10T20:47:55.115Z","videoConferenceLink":"https://us02web.zoom.us/j/84287875531?pwd=WFRORWRmVlhUWHdpTzlGVUlBWTF6UT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9889a85983001f385877","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-03-15T17:00:00.051Z","startTime":"2023-03-15T17:00:00.051Z","endTime":"2023-03-15T18:00:00.051Z","hours":1,"createdDate":"2023-03-10T20:52:19.052Z","updatedDate":"2023-03-10T20:52:19.052Z","videoConferenceLink":"https://us02web.zoom.us/j/82971740261?pwd=aEJvUFpiWTJCNHBqQWRMQUFMaW80UT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b99dfa85983001f385878","name":"PM Prep for All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-08-11T02:17:29.860Z","startTime":"2023-08-07T16:30:00.860Z","endTime":"2023-08-07T17:00:00.860Z","hours":0.5,"createdDate":"2023-03-10T20:58:06.986Z","updatedDate":"2023-08-08T02:17:29.860Z","videoConferenceLink":"https://us02web.zoom.us/j/87362760900?pwd=R3lUZStVUFdXOWl6R29ObXF0d2lGZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9a34a85983001f385879","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-08-11T02:12:52.668Z","startTime":"2023-08-07T17:00:00.668Z","endTime":"2023-08-07T18:00:00.668Z","hours":1,"createdDate":"2023-03-10T20:59:31.803Z","updatedDate":"2023-08-08T02:12:52.668Z","videoConferenceLink":"https://us02web.zoom.us/j/87362760900?pwd=R3lUZStVUFdXOWl6R29ObXF0d2lGZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9ae5a85983001f38587a","name":"UX Lead/PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-08-10T02:13:36.139Z","startTime":"2023-08-07T23:00:00.139Z","endTime":"2023-08-08T00:00:00.139Z","hours":1,"createdDate":"2023-03-10T21:02:29.365Z","updatedDate":"2023-08-08T02:13:36.139Z","videoConferenceLink":"https://us02web.zoom.us/j/81955868970?pwd=ekcrYjdUODkxcXlPNjE0YmxESkUwUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9bd8a85983001f38587b","name":"UX","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-03-14T22:00:00.226Z","startTime":"2023-03-14T22:00:00.226Z","endTime":"2023-03-14T23:00:00.226Z","hours":1,"createdDate":"2023-03-10T21:06:32.226Z","updatedDate":"2023-03-10T21:06:32.226Z","videoConferenceLink":"https://us02web.zoom.us/j/83834020199?pwd=em9sSy9jdit5RTRHQWZ3NFNGUVg4Zz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640bb91afad84600219def22","name":"PM/Org","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"6407cb7ce587a20020ebcec6","name":"Tables","projectStatus":"Active","createdDate":"2023-03-07T23:40:44.377Z","__v":0,"hflaWebsiteUrl":"","githubUrl":"https://github.com/hackforla/tables-public"},"date":"2023-08-18T15:55:31.782Z","startTime":"2023-08-15T00:30:00.782Z","endTime":"2023-08-15T01:30:00.782Z","hours":1,"createdDate":"2023-03-10T23:11:21.610Z","updatedDate":"2023-08-14T15:55:31.782Z","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640fd959b0b3a80020cd7bac","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["TBD"],"managedByUsers":[],"_id":"5edeac78ce228b001778facd","name":"VRMS","description":"VRMS is a tool used for the engagement, support, and retention of a network of volunteers.","githubIdentifier":"226157870","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/VRMS","slackUrl":"https://hackforla.slack.com/archives/CRGH5HM0Q","googleDriveUrl":"https://drive.google.com/drive/folders/1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","googleDriveId":"1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","hflaWebsiteUrl":"https://www.hackforla.org/projects/vrms","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- Front end devs (any level) \n - Back end devs (any level)","createdDate":"2020-06-08T21:24:08.313Z","__v":0},"date":"2023-08-14T23:21:09.776Z","startTime":"2023-08-11T02:00:00.776Z","endTime":"2023-08-11T03:00:00.776Z","hours":1,"createdDate":"2023-03-14T02:18:01.153Z","updatedDate":"2023-08-10T23:21:09.776Z","videoConferenceLink":"https://www.hackforla.org/projects/vrms","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6419115a52db6500200a1f84","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills (branches, separation of concerns, etc.). We are currently in a redesign phase, using CI/CD in the run up to demoing the new version at Code for America's Summit 2020 in Washington, D.C.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"date":"2023-03-26T16:00:00.782Z","startTime":"2023-03-26T16:00:00.782Z","endTime":"2023-03-26T17:00:00.782Z","hours":1,"createdDate":"2023-03-21T02:07:22.782Z","updatedDate":"2023-03-21T02:07:22.782Z","videoConferenceLink":"https://us02web.zoom.us/j/82177492860?pwd=UGNYdmJXMXgvVmZiSGtETTR4VGV6Zz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6419f6c13f2c51001fb2a1c2","name":"Dev Leads/PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills (branches, separation of concerns, etc.). We are currently in a redesign phase, using CI/CD in the run up to demoing the new version at Code for America's Summit 2020 in Washington, D.C.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"date":"2023-08-14T23:21:51.457Z","startTime":"2023-08-11T00:00:00.457Z","endTime":"2023-08-11T02:00:00.457Z","hours":2,"createdDate":"2023-03-21T18:26:11.199Z","updatedDate":"2023-08-10T23:21:51.457Z","videoConferenceLink":"https://us06web.zoom.us/j/89011346147?pwd=R280emlKVnRtTmF3RURrWFZ2d21zQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b667ba403830020e638db","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Code for America (CfA)","CfA National Advisory Council","Code for Boston","Code for Charlottesville"],"managedByUsers":[],"_id":"6086fe5792e3bf053b2954c4","name":"BOP","description":"This project aims to improve existing structures and create new ones that make it easier to share replicable processes and practices so that organizers and members can iterate on each others work, improving outcomes for the whole network.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/codeforamerica/brigade-playbook","slackUrl":"https://cfa.slack.com/archives/G0196272BBN","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/brigade-organizers-playbook","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-08-19T00:00:00.000Z","__v":0},"date":"2023-08-09T01:58:36.242Z","startTime":"2023-08-07T16:00:00.242Z","endTime":"2023-08-07T17:00:00.242Z","hours":1,"createdDate":"2023-03-22T20:35:07.228Z","updatedDate":"2023-08-08T01:58:36.242Z","videoConferenceLink":"https://codeforamerica.zoom.us/j/98602227448?pwd=dVgyeld1dXBjbWlBaUQ5RzU5UkVpdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b66b9a403830020e638dc","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Code for America (CfA)","CfA National Advisory Council","Code for Boston","Code for Charlottesville"],"managedByUsers":[],"_id":"6086fe5792e3bf053b2954c4","name":"BOP","description":"This project aims to improve existing structures and create new ones that make it easier to share replicable processes and practices so that organizers and members can iterate on each others work, improving outcomes for the whole network.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/codeforamerica/brigade-playbook","slackUrl":"https://cfa.slack.com/archives/G0196272BBN","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/brigade-organizers-playbook","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-08-19T00:00:00.000Z","__v":0},"date":"2023-08-20T16:08:59.217Z","startTime":"2023-08-14T15:00:00.217Z","endTime":"2023-08-14T16:00:00.217Z","hours":1,"createdDate":"2023-03-22T20:36:09.917Z","updatedDate":"2023-08-14T16:08:59.217Z","videoConferenceLink":"https://us02web.zoom.us/j/83945450679?pwd=VGY4QXNPMjRidTVKZERpVjduNVJXdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b684ca403830020e638dd","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"603e8471b6e1b403ab81abe7","name":"Community of Practice: Product Management","description":"A place for leads to communicate with each other and with the leadership team.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/product-management","slackUrl":"https://hackforla.slack.com/archives/C010LNXH2JY","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"https://us02web.zoom.us/j/81435536017?pwd=eHNtNm5SVnpickxqUHRlbFJtS2tJUT09","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2023-03-24T19:00:00.454Z","startTime":"2023-03-24T19:00:00.454Z","endTime":"2023-03-24T20:00:00.454Z","hours":1,"createdDate":"2023-03-22T20:42:52.454Z","updatedDate":"2023-03-22T20:42:52.454Z","videoConferenceLink":"https://us02web.zoom.us/j/83795143399?pwd=QnJQdG8vSmhocG5FQXBEVGVrSUx4UT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b7681343d38001f81d1c9","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2023-09-12T16:20:23.674Z","startTime":"2023-09-08T00:30:00.675Z","endTime":"2023-09-08T01:30:00.675Z","hours":1,"createdDate":"2023-03-22T21:43:29.342Z","updatedDate":"2023-09-07T16:20:23.674Z","videoConferenceLink":"https://us02web.zoom.us/j/87885175045?pwd=VUh1Y2VmakhqQ2hKeWtwVGRYV21XUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b9551cdea2c001e0df377","name":"UXR","hacknight":"Online","eventType":"Team Meeting","description":"alternate week","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2023-08-01T17:53:01.958Z","startTime":"2023-07-31T01:30:00.958Z","endTime":"2023-07-31T02:30:00.958Z","hours":1,"createdDate":"2023-03-22T23:54:56.667Z","updatedDate":"2023-07-30T17:53:01.958Z","videoConferenceLink":"https://stonybrook.zoom.us/j/7917944462","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b95becdea2c001e0df378","name":"Leads/PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2023-08-11T01:49:23.755Z","startTime":"2023-08-07T01:00:00.755Z","endTime":"2023-08-07T02:00:00.755Z","hours":1,"createdDate":"2023-03-22T23:56:46.052Z","updatedDate":"2023-08-07T01:49:23.755Z","videoConferenceLink":"https://us02web.zoom.us/j/83622484566?pwd=WE5kZG5uZ3RWVzdoTm1IRU5SMmVlZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b964bcdea2c001e0df379","name":"Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2023-08-17T15:35:20.510Z","startTime":"2023-08-15T02:00:00.510Z","endTime":"2023-08-15T03:00:00.510Z","hours":1,"createdDate":"2023-03-22T23:59:07.197Z","updatedDate":"2023-08-14T15:35:20.510Z","videoConferenceLink":"https://us02web.zoom.us/j/82140923894?pwd=NHlzdXNNb2Zxdk9WZm0raVFjc01BUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64397c32f15295001f3ae51c","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6a98b87ed80001942b10a","name":"Guides Team","projectStatus":"Active","createdDate":"2023-01-29T17:14:51.760Z","__v":0,"description":"Creating guides and templates from the effective practices that HfLA has developed and iterated from our projects. HfLA Guides aim to share replicable processes and practices from Engineering, UI/UX, Product Management, Data Science, Marketing Fundraising, DevOps, Admin, and Professional Development. The project seeks to further grow HfLA’s peer learning and iterative culture, and ultimately improve outcomes for the entire civic tech ecosystem.","githubUrl":"https://github.com/hackforla/guides","slackUrl":"https://hackforla.slack.com/archives/C028T9XU9S5","hflaWebsiteUrl":"https://www.hackforla.org/projects/guides-team","githubIdentifier":"386323061","googleDriveUrl":"https://drive.google.com/drive/folders/0AOyia66xiVyGUk9PVA","location":"https://us06web.zoom.us/j/85331955066?pwd=35naUwc1pLrvcQdBEwlTMPQZafcH9d.1"},"date":"2023-08-18T15:39:43.970Z","startTime":"2023-08-14T14:30:00.970Z","endTime":"2023-08-14T16:00:00.970Z","hours":1.5,"createdDate":"2023-04-14T16:15:46.025Z","updatedDate":"2023-08-14T15:39:43.970Z","videoConferenceLink":"https://us02web.zoom.us/j/84639292835?pwd=eG1DNUVuTEZPbVp4VjhQeWQ4MVkvZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"645fcd889057b4001d20cf35","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2023-08-30T20:57:58.299Z","startTime":"2023-08-31T02:00:00.300Z","endTime":"2023-08-31T03:00:00.300Z","hours":1,"createdDate":"2023-05-13T17:48:56.369Z","updatedDate":"2023-08-30T20:57:58.299Z","videoConferenceLink":"https://us02web.zoom.us/j/81644568036?pwd=RllXN3RzaTFpTHJIeU4wNGo4TS9WUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"645fce729057b4001d20cf36","name":"Stakeholder Prep","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2023-08-17T15:04:25.314Z","startTime":"2023-08-14T20:00:00.314Z","endTime":"2023-08-14T21:00:00.314Z","hours":1,"createdDate":"2023-05-13T17:52:49.824Z","updatedDate":"2023-08-14T15:04:25.314Z","videoConferenceLink":"https://us02web.zoom.us/j/83270067282?pwd=dnhVelQ2YnFUcmhXSEhUL0tuUURXQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64922028841c83002296b2e3","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["TBD"],"managedByUsers":[],"_id":"5edeac78ce228b001778facd","name":"VRMS","description":"VRMS is a tool used for the engagement, support, and retention of a network of volunteers.","githubIdentifier":"226157870","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/VRMS","slackUrl":"https://hackforla.slack.com/archives/CRGH5HM0Q","googleDriveUrl":"https://drive.google.com/drive/folders/1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","googleDriveId":"1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","hflaWebsiteUrl":"https://www.hackforla.org/projects/vrms","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- Front end devs (any level) \n - Back end devs (any level)","createdDate":"2020-06-08T21:24:08.313Z","__v":0},"date":"2023-08-17T22:03:06.366Z","startTime":"2023-08-13T23:00:00.366Z","endTime":"2023-08-14T00:00:00.366Z","hours":1,"createdDate":"2023-06-20T21:54:48.403Z","updatedDate":"2023-08-13T22:03:06.366Z","videoConferenceLink":"https://us06web.zoom.us/j/83499139032?pwd=Rm80SHRBWnJXV3pvUDUycFVmZUp4dz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6495f032a2eeb0002020688f","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2023-09-13T17:42:55.125Z","startTime":"2023-09-09T02:00:00.125Z","endTime":"2023-09-09T03:00:00.125Z","hours":1,"createdDate":"2023-06-23T19:19:14.214Z","updatedDate":"2023-09-08T17:42:55.125Z","videoConferenceLink":"https://us06web.zoom.us/j/83626721699?pwd=VUhITjRyY2FTQzRhc0NwRnFOREJDdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64961cd3a75c2c0020ae4f87","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"1st week","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2023-09-13T17:43:16.802Z","startTime":"2023-09-09T02:00:00.802Z","endTime":"2023-09-09T03:00:00.802Z","hours":1,"createdDate":"2023-06-23T22:29:38.825Z","updatedDate":"2023-09-08T17:43:16.802Z","videoConferenceLink":"https://us06web.zoom.us/j/82617071267?pwd=bEFmOVZYTDREanhGbjZQOFdWR0NxUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bc1bbc4f7f0027f23e32","name":"Dev","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2023-09-14T20:22:38.192Z","startTime":"2023-09-09T01:00:00.192Z","endTime":"2023-09-09T02:00:00.192Z","hours":1,"createdDate":"2023-06-26T16:26:03.554Z","updatedDate":"2023-09-08T20:22:38.192Z","videoConferenceLink":"https://us06web.zoom.us/j/88325048774?pwd=bGNLUmFoN2Q5b1lzZENyY25sSWlxZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bc75bc4f7f0027f23e33","name":"Content","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-02-09T01:28:47.347Z","startTime":"2024-02-08T22:00:00.347Z","endTime":"2024-02-08T23:00:00.347Z","hours":1,"createdDate":"2023-06-26T16:27:33.676Z","updatedDate":"2024-02-09T01:28:47.347Z","videoConferenceLink":"https://us06web.zoom.us/j/85133711993?pwd=VSrI2qW0akve2AbbaWmGHTaZJgSbmf.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bcc2bc4f7f0027f23e34","name":"Design/Content","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2023-08-04T17:50:48.507Z","startTime":"2023-07-30T16:30:00.507Z","endTime":"2023-07-30T17:30:00.507Z","hours":1,"createdDate":"2023-06-26T16:28:50.770Z","updatedDate":"2023-07-30T17:50:48.507Z","videoConferenceLink":"https://us02web.zoom.us/j/87083658463?pwd=K3ZPZnNyZ3hFTVV1Vlc2Y1NPYmNDZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bce7bc4f7f0027f23e35","name":"Research","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2023-08-04T17:50:53.135Z","startTime":"2023-07-30T18:00:00.135Z","endTime":"2023-07-30T19:00:00.135Z","hours":1,"createdDate":"2023-06-26T16:29:27.456Z","updatedDate":"2023-07-30T17:50:53.135Z","videoConferenceLink":"https://us02web.zoom.us/j/86353515192?pwd=VHRDOWFlZCtwOFNrdGpQdUk5R2YzUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499be26c0de5700203a5510","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"2nd week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2023-09-08T20:15:41.389Z","startTime":"2023-09-08T17:30:00.389Z","endTime":"2023-09-08T18:30:00.389Z","hours":1,"createdDate":"2023-06-26T16:34:46.085Z","updatedDate":"2023-09-08T20:15:41.389Z","videoConferenceLink":"https://us06web.zoom.us/j/84526661131?pwd=eDBOY2Nnejh1VmJRTGY2N09lenNhZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"649dc7a77c703d00245c34a6","name":"Dev/Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-08-02T02:34:30.293Z","startTime":"2023-07-31T20:00:00.293Z","endTime":"2023-07-31T21:00:00.293Z","hours":1,"createdDate":"2023-06-29T18:04:23.399Z","updatedDate":"2023-08-01T02:34:30.293Z","videoConferenceLink":"https://us02web.zoom.us/j/88548175319?pwd=bHZhOUxpTWZpclZLbUFTMGxFT2pvQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64da4c5a21bb24002091e958","name":"PM/Org","hacknight":"Online","eventType":"Team Meeting","description":"scheduled as needed","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2023-08-18T20:00:00.918Z","startTime":"2023-08-18T20:00:00.918Z","endTime":"2023-08-18T21:00:00.918Z","hours":1,"createdDate":"2023-08-14T15:46:35.918Z","updatedDate":"2023-08-14T15:46:35.918Z","videoConferenceLink":"https://us02web.zoom.us/j/83738091907?pwd=VjBqY1Q3aTRkUmJISkxDaXprK29xQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64da4cf321bb24002091e959","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"6407cb7ce587a20020ebcec6","name":"Tables","projectStatus":"Active","createdDate":"2023-03-07T23:40:44.377Z","__v":0,"hflaWebsiteUrl":"","githubUrl":"https://github.com/hackforla/tables-public"},"date":"2023-08-19T01:30:00.766Z","startTime":"2023-08-19T01:30:00.766Z","endTime":"2023-08-19T02:30:00.766Z","hours":1,"createdDate":"2023-08-14T15:49:09.766Z","updatedDate":"2023-08-14T15:49:09.766Z","videoConferenceLink":"https://us02web.zoom.us/j/81309906141?pwd=SENlVVBYRVFtR3NDV1dBNyszcmsxdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64eea5136b9ee100206f94b5","name":"UX Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2023-09-03T23:00:00.880Z","startTime":"2023-09-03T23:00:00.880Z","endTime":"2023-09-04T00:00:00.880Z","hours":1,"createdDate":"2023-08-30T02:10:26.880Z","updatedDate":"2023-08-30T02:10:26.880Z","videoConferenceLink":"https://meet.google.com/imb-hbsr-swj","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f73b6296eab500228642b8","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2023-09-14T17:43:31.520Z","startTime":"2023-09-09T02:00:00.520Z","endTime":"2023-09-09T03:00:00.520Z","hours":1,"createdDate":"2023-09-05T14:30:05.578Z","updatedDate":"2023-09-08T17:43:31.520Z","videoConferenceLink":"https://us06web.zoom.us/j/87979035538?pwd=ZGtiU1FJeTN0V3BFNXYyMDYvN08yUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f740837211620022f7757e","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"64f740007211620022f7757d","name":"Community of Practice: CoP Leads","description":"The Leads Meeting for All the CoPs","location":"https://us02web.zoom.us/s/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","githubUrl":"https://github.com/hackforla/communities-of-practice","slackUrl":"https://hackforla.slack.com/archives/C026UMZK89X","googleDriveUrl":"https://drive.google.com/drive/folders/0AHDu27vDmN91Uk9PVA","projectStatus":"Active","createdDate":"2023-09-05T14:49:36.374Z","__v":0,"githubIdentifier":"337874660","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice"},"date":"2023-09-07T01:00:00.752Z","startTime":"2023-09-07T01:00:00.752Z","endTime":"2023-09-07T02:00:00.752Z","hours":1,"createdDate":"2023-09-05T14:51:58.752Z","updatedDate":"2023-09-05T14:51:58.752Z","videoConferenceLink":"https://us02web.zoom.us/j/86196694131?pwd=YVpCR1NWa0s4RmhkcjQ1cFdQSFZiUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f74653dfa4320020688749","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605772bb46b7cd034719d114","name":"Community of Practice: Software Engineering","description":"Community of Practice for Software Engineers","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/engineering","slackUrl":"https://hackforla.slack.com/archives/C01CU709SER","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2023-09-11T02:00:00.958Z","startTime":"2023-09-11T02:00:00.958Z","endTime":"2023-09-11T02:30:00.958Z","hours":0.5,"createdDate":"2023-09-05T15:16:46.959Z","updatedDate":"2023-09-05T15:16:46.959Z","videoConferenceLink":"https://us06web.zoom.us/j/88450399932?pwd=NUpMeGM2ZS85VWp4b3QwbUtTT0FCZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f76e2574597c0020feef75","name":"Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience"},"date":"2023-09-05T19:30:00.941Z","startTime":"2023-09-05T19:30:00.941Z","endTime":"2023-09-05T20:00:00.941Z","hours":0.5,"createdDate":"2023-09-05T18:06:40.942Z","updatedDate":"2023-09-05T18:06:40.942Z","videoConferenceLink":"https://us06web.zoom.us/j/89505679972?pwd=c0QzS1JFQkxoZGdYaU16VmdzcEhXUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6503252a26c03f00229adaf0","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0},"date":"2023-09-20T19:00:00.053Z","startTime":"2023-09-20T19:00:00.053Z","endTime":"2023-09-20T20:00:00.053Z","hours":1,"createdDate":"2023-09-14T15:22:20.053Z","updatedDate":"2023-09-14T15:22:20.053Z","videoConferenceLink":"https://us06web.zoom.us/j/89741924912?pwd=bqSrHEszyfv6p90SmOt66vCDLuz5ol.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6503257c26c03f00229adaf1","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0},"date":"2023-09-18T14:00:00.935Z","startTime":"2023-09-18T14:00:00.935Z","endTime":"2023-09-18T17:00:00.935Z","hours":3,"createdDate":"2023-09-14T15:23:42.935Z","updatedDate":"2023-09-14T15:23:42.935Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6503259826c03f00229adaf2","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0},"date":"2023-09-19T14:00:00.280Z","startTime":"2023-09-19T14:00:00.280Z","endTime":"2023-09-19T17:00:00.280Z","hours":3,"createdDate":"2023-09-14T15:24:10.280Z","updatedDate":"2023-09-14T15:24:10.280Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"650325ae26c03f00229adaf3","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0},"date":"2023-09-20T14:00:00.771Z","startTime":"2023-09-20T14:00:00.771Z","endTime":"2023-09-20T17:00:00.771Z","hours":3,"createdDate":"2023-09-14T15:24:32.771Z","updatedDate":"2023-09-14T15:24:32.771Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"650325d226c03f00229adaf4","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0},"date":"2023-09-14T14:00:00.160Z","startTime":"2023-09-14T14:00:00.160Z","endTime":"2023-09-14T17:00:00.160Z","hours":3,"createdDate":"2023-09-14T15:25:08.160Z","updatedDate":"2023-09-14T15:25:08.160Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"650325e726c03f00229adaf5","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0},"date":"2023-09-15T14:00:00.505Z","startTime":"2023-09-15T14:00:00.505Z","endTime":"2023-09-15T17:00:00.505Z","hours":3,"createdDate":"2023-09-14T15:25:29.505Z","updatedDate":"2023-09-14T15:25:29.505Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6514d16f609cb4002070f9b4","name":"Mtesty face","hacknight":"Online","eventType":"Team Meeting","description":"Qqq","project":{"recruitingCategories":[],"partners":["Josh"],"managedByUsers":["Josh"],"_id":"644748563212e6001fbca24a","name":"Testing","description":"testy","location":"www.test.com","githubUrl":"updated_github_address.com","slackUrl":"updated_slack_channel.com","googleDriveUrl":"updated_google_drive.com","projectStatus":"Active","createdDate":"2023-04-25T03:26:14.482Z","__v":0,"githubIdentifier":"Spiteless","hflaWebsiteUrl":"updated_website.com/test34","googleDriveId":"update_google_drive_id23"},"date":"2023-11-08T19:29:18.524Z","startTime":"2023-11-06T06:00:00.524Z","endTime":"2023-11-06T07:00:00.524Z","hours":1,"createdDate":"2023-09-28T01:05:51.900Z","updatedDate":"2023-11-05T19:29:18.524Z","videoConferenceLink":"Q.qq","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"65665b6ae1a41b0022515eca","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"1st week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2023-11-28T21:30:28.722Z","startTime":"2023-11-29T01:00:00.722Z","endTime":"2023-11-29T02:00:00.722Z","hours":1,"createdDate":"2023-11-28T21:28:10.060Z","updatedDate":"2023-11-28T21:30:28.722Z","videoConferenceLink":"https://us06web.zoom.us/j/84729938240?pwd=YlBOd21vbE5PcVhHWTNObk05NlBrUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"65aecebd5530fe0025f9dad7","name":"Design/Data","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Code for America (CfA)","CfA National Advisory Council","Code for Boston","Code for Charlottesville"],"managedByUsers":[],"_id":"6086fe5792e3bf053b2954c4","name":"BOP","description":"This project aims to improve existing structures and create new ones that make it easier to share replicable processes and practices so that organizers and members can iterate on each others work, improving outcomes for the whole network.","githubIdentifier":"","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/codeforamerica/brigade-playbook","slackUrl":"https://cfa.slack.com/archives/G0196272BBN","googleDriveUrl":"","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/brigade-organizers-playbook","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-08-19T00:00:00.000Z","__v":0},"date":"2024-01-26T16:00:00.845Z","startTime":"2024-01-26T16:00:00.845Z","endTime":"2024-01-26T16:30:00.845Z","hours":0.5,"createdDate":"2024-01-22T20:23:24.845Z","updatedDate":"2024-01-22T20:23:24.845Z","videoConferenceLink":"https://us04web.zoom.us/j/2206070789?pwd=qCs2uCfM4LZeih3tbtfNeI4cqsVDZH.1&omn=79894920171","__v":0}] \ No newline at end of file +[{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123458"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb7240f509367be7272cf69","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5ec32abda973810017c0de0d","name":"Lucky Parking","description":"A platform looking for nearby street parking with least possibility of getting citation.","githubIdentifier":"216854923","projectStatus":"Active","location":"Westside","githubUrl":"https://github.com/hackforla/lucky-parking","slackUrl":"https://hackforla.slack.com/archives/CPFDMSV6V","googleDriveUrl":"https://drive.google.com/drive/folders/1qq6w-eCvjxgfiQCCxPN9_0ah1DLTgl27","googleDriveId":"1qq6w-eCvjxgfiQCCxPN9_0ah1DLTgl27","hflaWebsiteUrl":"https://www.hackforla.org/projects/lucky-parking","videoConferenceLink":"https://us02web.zoom.us/j/84817446708?pwd=QW5RVER2SkVTWnZkN25ZY2d2RzNTdz09","lookingDescription":"- Frontend Software Engineer \n- Backend Software Engineer \n- Advanced Data Scientist \n- Python Enthusiast","createdDate":"2020-05-19T00:39:25.640Z","__v":0},"date":"2024-03-05T02:00:00.092Z","startTime":"2024-03-05T02:00:00.092Z","endTime":"2024-03-05T03:00:00.092Z","hours":1,"createdDate":"2020-05-09T21:43:43.519Z","updatedDate":"2024-03-05T03:33:22.092Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/89121722043?pwd=VFlhSUlzbVhpNVBqQmNWd1lSMWFWZz09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb72878509367be7272cf6d","hacknight":"Online","name":"PM","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-10-14T23:00:00.243Z","startTime":"2024-10-14T23:00:00.243Z","endTime":"2024-10-15T00:00:00.243Z","hours":1,"createdDate":"2020-05-09T22:02:32.097Z","updatedDate":"2024-10-11T21:27:54.243Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/89798814732?pwd=LPDAZBoWNLLcbPXdOAjXzneTGTbNtv.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb72b05509367be7272cf71","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2024-08-21T01:30:00.764Z","startTime":"2024-08-21T01:30:00.764Z","endTime":"2024-08-21T03:00:00.764Z","hours":0.5,"createdDate":"2020-05-09T22:13:25.167Z","updatedDate":"2024-08-16T19:34:41.764Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/87595945272?pwd=bWFzaWdtMWk3WWdjbU00TmhrcnM0dz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb73139509367be7272cf75","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["TBD"],"managedByUsers":[],"_id":"5edeae6cce228b001778face","name":"Community of Practice: DevOps","description":"Operations is a broad area that includes information technology work on devops, infrastructure as code, hosting, pipelines, services, security, practices, and more. ","githubIdentifier":"246449481","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/ops","slackUrl":"https://hackforla.slack.com/archives/CV7QGL66B","googleDriveUrl":"https://drive.google.com/drive/folders/0AAX-8be-yD5JUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-06-08T21:32:28.164Z","__v":0},"date":"2024-04-11T01:00:00.389Z","startTime":"2024-04-11T01:00:00.389Z","endTime":"2024-04-11T02:00:00.389Z","hours":1,"createdDate":"2020-05-09T22:39:53.054Z","updatedDate":"2024-04-11T02:18:30.389Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/88266718430?pwd=UFNTTUcxWkxHQ0NVYm5OK3pRK0lPdz09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eb736bf509367be7272cf7e","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/0AKWbU6_2dvZuUk9PVA","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"date":"2024-03-10T17:00:00.367Z","startTime":"2024-03-10T17:00:00.367Z","endTime":"2024-03-10T19:00:00.367Z","hours":2,"createdDate":"2020-05-09T23:03:27.242Z","updatedDate":"2024-03-05T03:33:48.367Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/82177492860?pwd=UGNYdmJXMXgvVmZiSGtETTR4VGV6Zz09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5ebb040346383ef9be2dc2d1","hacknight":"Online","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/0AKWbU6_2dvZuUk9PVA","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"name":"Dev","eventType":"Team Meeting","description":"","date":"2024-03-06T03:00:00.697Z","startTime":"2024-03-06T03:00:00.697Z","endTime":"2024-03-06T04:00:00.697Z","hours":1,"createdDate":"2020-05-12T20:16:03.981Z","updatedDate":"2024-03-05T03:34:29.697Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/85014559207?pwd=VnM4eDBrTnpVNWgwYUhnNDc3d2oyUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5eec3623411acc0017486999","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5eec356c411acc0017486997","name":"Community of Practice: Data Science","description":"The Hack For LA Data Science team is a Community of Practice within the LA brigade seeking to make analytical and machine learning services available to local communities and organizations.","githubIdentifier":"269486796","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/CGRATJCCF","googleDriveUrl":"https://drive.google.com/drive/folders/0ABybAQUv53kiUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-06-19T03:47:56.782Z","__v":0},"hacknight":"Westside","name":"All","eventType":"Team Meeting","description":"","date":"2024-03-05T03:00:00.384Z","startTime":"2024-03-05T03:00:00.384Z","endTime":"2024-03-05T04:00:00.384Z","hours":1,"createdDate":"2020-06-19T03:50:59.070Z","updatedDate":"2024-03-05T03:27:55.384Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/83423675645?pwd=anlnM0I3VGgxS3RJTGxCbnQ3Q09aQT09"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"5ff3d01210cf72445ce37e23","hacknight":"Online","name":"Design","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-03-07T01:00:00.316Z","startTime":"2024-03-07T01:00:00.316Z","endTime":"2024-03-07T02:00:00.316Z","hours":1,"createdDate":"2020-05-09T22:02:32.097Z","updatedDate":"2024-03-05T03:29:18.316Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/82255734768?pwd=WnVNU3BPUEZwNGVmYlZuZkN5SlkwZz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"603db433d7b86d36b4f28a63","hacknight":"Online","name":"All","eventType":"Community of Practice","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"603db1fbd7b86d36b4f28a62","name":"Community of Practice: UI/UX","description":"UI/UX Community of Practice","githubIdentifier":"327430594","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/UI-UX","slackUrl":"https://app.slack.com/client/T04502KQX/C017ESHSMNG","googleDriveUrl":"https://drive.google.com/drive/folders/0ACjCHzHKLLQxUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"https://us02web.zoom.us/j/89670251875?pwd=NTYySW5yL3YrYTRxcHRpK1V6YWdaQT09","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2024-03-07T02:00:00.750Z","startTime":"2024-03-07T02:00:00.750Z","endTime":"2024-03-07T03:00:00.750Z","hours":1,"createdDate":"2021-03-01T22:38:23.677Z","updatedDate":"2024-03-05T03:28:34.750Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/81630670134?pwd=RTNLRHlBSE1DeXRudkJJMHkzZGlVUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"605773e246b7cd034719d115","hacknight":"Online","name":"All","eventType":"Community of Practice","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605772bb46b7cd034719d114","name":"Community of Practice: Software Engineering","description":"Community of Practice for Software Engineers","githubIdentifier":"328256372","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/engineering","slackUrl":"https://hackforla.slack.com/archives/C01CU709SER","googleDriveUrl":"https://drive.google.com/drive/folders/0ALZlGXAx55mQUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2024-03-08T02:00:00.225Z","startTime":"2024-03-08T02:00:00.225Z","endTime":"2024-03-08T03:00:00.225Z","hours":1,"createdDate":"2021-03-21T22:38:23.677Z","updatedDate":"2024-03-05T03:28:27.225Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/85089810552?pwd=WWw3a0ZMQUdSOWdUcEQ3MWRUMDZEdz09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"605d5aba6fb945197a19038d","hacknight":"Online","name":"New Prospective Members","eventType":"Onboarding","description":"Alternating Mon/Tue. Click for schedule","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605d593b6fb945197a19038c","name":"Onboarding","description":"New participant onboarding","githubIdentifier":"380865495","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/admin","slackUrl":"https://hackforla.slack.com/archives/C04S7PNCU","googleDriveUrl":"https://drive.google.com/drive/folders/0APJFu_GrzzH7Uk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.meetup.com/hackforla/events","videoConferenceLink":"https://us02web.zoom.us/meeting/register/tZUtdeGvrTMoHtKkRwm7R8Kl8r9TXL73-UY9?_x_zm_rtaid=TNHnsFXoTF2IZlf-TUfrPw.1616083598988.a1e0d0f77cffa24ca0d6e75e25e23695&_x_zm_rhtaid=832","lookingDescription":"","createdDate":"2021-03-25T19:42:22.028Z","__v":0},"date":"2024-03-26T01:00:00.575Z","startTime":"2024-03-26T01:00:00.575Z","endTime":"2024-03-26T04:00:00.575Z","hours":3,"createdDate":"2021-03-25T22:38:23.677Z","updatedDate":"2024-03-22T19:35:08.575Z","__v":0,"videoConferenceLink":"https://zoom.us/"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"605d5bf66fb945197a19038e","hacknight":"Online","name":"New Prospective Members","eventType":"Onboarding","description":"Alternating Mon/Tue. Click for schedule","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605d593b6fb945197a19038c","name":"Onboarding","description":"New participant onboarding","githubIdentifier":"380865495","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/admin","slackUrl":"https://hackforla.slack.com/archives/C04S7PNCU","googleDriveUrl":"https://drive.google.com/drive/folders/0APJFu_GrzzH7Uk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.meetup.com/hackforla/events","videoConferenceLink":"https://us02web.zoom.us/meeting/register/tZUtdeGvrTMoHtKkRwm7R8Kl8r9TXL73-UY9?_x_zm_rtaid=TNHnsFXoTF2IZlf-TUfrPw.1616083598988.a1e0d0f77cffa24ca0d6e75e25e23695&_x_zm_rhtaid=832","lookingDescription":"","createdDate":"2021-03-25T19:42:22.028Z","__v":0},"date":"2024-03-27T01:00:00.592Z","startTime":"2024-03-27T01:00:00.592Z","endTime":"2024-03-27T04:00:00.592Z","hours":3,"createdDate":"2021-03-25T22:38:23.677Z","updatedDate":"2024-03-22T19:35:10.592Z","__v":0,"videoConferenceLink":"https://zoom.us/"},{"location":{"city":"Santa Monica","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6126b9ff9b885ef7d95779e3","hacknight":"Online","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/0AKWbU6_2dvZuUk9PVA","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"name":"Dev Office Hours","eventType":"Team Meeting","description":"","date":"2024-03-08T03:00:00.151Z","startTime":"2024-03-08T03:00:00.151Z","endTime":"2024-03-08T04:00:00.151Z","hours":1,"createdDate":"2020-05-12T20:16:03.981Z","updatedDate":"2024-03-05T03:34:28.151Z","__v":0,"videoConferenceLink":"https://us02web.zoom.us/j/84412621807?pwd=NTN2eFBtNDg1U05nUWV3UEJuSHpaUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"61b7fc8d71f7e8fa9f644ff8","hacknight":"Online","name":"PM","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2024-08-23T01:00:00.010Z","startTime":"2024-08-23T01:00:00.010Z","endTime":"2024-08-23T02:00:00.010Z","hours":1,"createdDate":"2021-12-13T22:13:25.167Z","updatedDate":"2024-08-16T19:35:42.010Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/88234426474?pwd=bR0kUkJB7BWpUWiaDbLl6bprg0bpKD.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"61b7fd5471f7e8fa9f644ffa","hacknight":"Online","name":"PM/Org","eventType":"Team Meeting","description":"alternating week","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2024-08-21T01:00:00.881Z","startTime":"2024-08-21T01:00:00.881Z","endTime":"2024-08-21T01:30:00.881Z","hours":0.5,"createdDate":"2020-05-09T23:17:12.078Z","updatedDate":"2024-08-16T19:33:16.881Z","__v":0,"videoConferenceLink":"https://meet.google.com/pxe-sqfn-sdu?authuser=1&hs=122"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620998d72720480f934e4365","hacknight":"Online","name":"All","eventType":"Team Meeting","description":"3rd week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"297491982","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMdnUkSXicNCUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-03-06T01:00:00.681Z","startTime":"2024-03-06T01:00:00.681Z","endTime":"2024-03-06T02:00:00.681Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2024-03-05T03:27:30.681Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/84729938240?pwd=YlBOd21vbE5PcVhHWTNObk05NlBrUT09"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6209995f2720480f934e4366","hacknight":"Online","name":"UXR","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"297491982","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMdnUkSXicNCUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-09-06T19:00:00.456Z","startTime":"2024-09-06T19:00:00.456Z","endTime":"2024-09-06T20:00:00.456Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2024-09-05T03:52:26.456Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/88694734855?pwd=HMuckXblBkyoNUENmR4duKWnDaNTye.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620999902720480f934e4367","hacknight":"Online","name":"Dev","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"297491982","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMdnUkSXicNCUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-09-06T02:00:00.496Z","startTime":"2024-09-06T02:00:00.496Z","endTime":"2024-09-06T03:00:00.496Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2024-09-05T03:51:43.496Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/88662978784?pwd=4koLjZhrXlrcHXYQp19BkGtYF4vHUy.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620999f92720480f934e4368","hacknight":"Online","name":"PM/Org","eventType":"Team Meeting","description":"2nd week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"297491982","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMdnUkSXicNCUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-09-09T22:30:00.931Z","startTime":"2024-09-09T22:30:00.931Z","endTime":"2024-09-09T23:30:00.931Z","hours":1,"createdDate":"2022-02-13T22:13:25.167Z","updatedDate":"2024-09-05T03:50:43.931Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/81031561471?pwd=KrEnnuposREUCTBVqGaAJaCY9NRK8j.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"620bd0be68255664fc376985","hacknight":"Online","name":"PM/Org","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-09-19T01:00:00.565Z","startTime":"2024-09-19T01:00:00.565Z","endTime":"2024-09-19T02:00:00.565Z","hours":1,"createdDate":"2020-05-09T22:51:16.674Z","updatedDate":"2024-09-13T18:05:01.565Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/87350455396?pwd=Ieitc3wHTQcurB8SXjedJMHug2i9nQ.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"63e1c86c132477014ec310ff","hacknight":"Online","name":"Dev","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-09-17T01:00:00.119Z","startTime":"2024-09-17T01:00:00.119Z","endTime":"2024-09-17T02:00:00.119Z","hours":2,"createdDate":"2020-05-09T22:51:16.674Z","updatedDate":"2024-09-13T18:03:05.119Z","__v":0,"videoConferenceLink":"https://us06web.zoom.us/j/83988547775?pwd=ZoNDtueAbdjyMgIvoQAmh4DGIarM3Z.1"},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"63e58d020f41f6001f62da50","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63e58b5c0f41f6001f62da4f","name":"People Depot","projectStatus":"Active","createdDate":"2023-02-10T00:10:04.622Z","__v":0,"githubUrl":"https://github.com/hackforla/peopledepot/","slackUrl":"https://hackforla.slack.com/archives/C02PTACSRJQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMVDRCjyzDgtUk9PVA","location":"Remote","description":"PeopleDepot aims to provide a single source of truth as the backend infrastructure and data store for Hack for LA projects, including data about people, program areas, and projects. PeopleDepot uses PostgreSQL for its database and Django as the backend data model framework with Django REST Framework for the API layer. PeopleDepot's goal is to serve as a repository of information for other infrastructure projects (e.g., VRMS, Hack for LA Website, Civic Tech Index, Tables, etc).","hflaWebsiteUrl":""},"date":"2024-10-18T00:00:00.428Z","startTime":"2024-10-18T00:00:00.428Z","endTime":"2024-10-18T01:00:00.428Z","hours":1,"createdDate":"2023-02-10T00:17:04.802Z","updatedDate":"2024-10-15T19:10:34.428Z","videoConferenceLink":"https://us06web.zoom.us/j/88230844471?pwd=YW1CMElDNEoxNmhTb1NwS1ZFa3BJQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b93ed861655001a9d8a1a","name":"Stakeholder","hacknight":"Online","eventType":"Team Meeting","description":"Every other Tuesday","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2024-04-09T23:00:00.924Z","startTime":"2024-04-09T23:00:00.924Z","endTime":"2024-04-10T00:00:00.924Z","hours":1,"createdDate":"2023-03-10T20:32:39.889Z","updatedDate":"2024-04-09T03:34:32.924Z","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b977ba85983001f385876","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience","description":"The Tech Work Experience project is a structured summer internship program for college and high school students to work on open source projects in the fields of software, product development, project management, and UI/UX design","githubIdentifier":"376872876","githubUrl":"https://github.com/hackforla/internship","googleDriveUrl":"https://drive.google.com/drive/folders/0ACgRrPVkhnrvUk9PVA","slackUrl":"https://github.com/hackforla/internship"},"date":"2024-03-04T18:00:00.394Z","startTime":"2024-03-04T18:00:00.394Z","endTime":"2024-03-04T19:00:00.394Z","hours":1,"createdDate":"2023-03-10T20:47:55.115Z","updatedDate":"2024-03-05T03:27:41.394Z","videoConferenceLink":"https://us02web.zoom.us/j/84287875531?pwd=WFRORWRmVlhUWHdpTzlGVUlBWTF6UT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b99dfa85983001f385878","name":"PM Prep for All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience","description":"The Tech Work Experience project is a structured summer internship program for college and high school students to work on open source projects in the fields of software, product development, project management, and UI/UX design","githubIdentifier":"376872876","githubUrl":"https://github.com/hackforla/internship","googleDriveUrl":"https://drive.google.com/drive/folders/0ACgRrPVkhnrvUk9PVA","slackUrl":"https://github.com/hackforla/internship"},"date":"2024-03-07T17:30:00.911Z","startTime":"2024-03-07T17:30:00.911Z","endTime":"2024-03-07T18:00:00.911Z","hours":0.5,"createdDate":"2023-03-10T20:58:06.986Z","updatedDate":"2024-03-05T03:27:55.911Z","videoConferenceLink":"https://us02web.zoom.us/j/87362760900?pwd=R3lUZStVUFdXOWl6R29ObXF0d2lGZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9a34a85983001f385879","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience","description":"The Tech Work Experience project is a structured summer internship program for college and high school students to work on open source projects in the fields of software, product development, project management, and UI/UX design","githubIdentifier":"376872876","githubUrl":"https://github.com/hackforla/internship","googleDriveUrl":"https://drive.google.com/drive/folders/0ACgRrPVkhnrvUk9PVA","slackUrl":"https://github.com/hackforla/internship"},"date":"2024-03-07T18:00:00.278Z","startTime":"2024-03-07T18:00:00.278Z","endTime":"2024-03-07T19:00:00.278Z","hours":1,"createdDate":"2023-03-10T20:59:31.803Z","updatedDate":"2024-03-05T03:27:59.278Z","videoConferenceLink":"https://us02web.zoom.us/j/87362760900?pwd=R3lUZStVUFdXOWl6R29ObXF0d2lGZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9ae5a85983001f38587a","name":"UX Lead/PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience","description":"The Tech Work Experience project is a structured summer internship program for college and high school students to work on open source projects in the fields of software, product development, project management, and UI/UX design","githubIdentifier":"376872876","githubUrl":"https://github.com/hackforla/internship","googleDriveUrl":"https://drive.google.com/drive/folders/0ACgRrPVkhnrvUk9PVA","slackUrl":"https://github.com/hackforla/internship"},"date":"2024-03-07T00:00:00.010Z","startTime":"2024-03-07T00:00:00.010Z","endTime":"2024-03-07T01:00:00.010Z","hours":1,"createdDate":"2023-03-10T21:02:29.365Z","updatedDate":"2024-03-05T03:27:53.010Z","videoConferenceLink":"https://us02web.zoom.us/j/81955868970?pwd=ekcrYjdUODkxcXlPNjE0YmxESkUwUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640b9bd8a85983001f38587b","name":"UX","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience","description":"The Tech Work Experience project is a structured summer internship program for college and high school students to work on open source projects in the fields of software, product development, project management, and UI/UX design","githubIdentifier":"376872876","githubUrl":"https://github.com/hackforla/internship","googleDriveUrl":"https://drive.google.com/drive/folders/0ACgRrPVkhnrvUk9PVA","slackUrl":"https://github.com/hackforla/internship"},"date":"2024-03-05T23:00:00.244Z","startTime":"2024-03-05T23:00:00.244Z","endTime":"2024-03-06T00:00:00.244Z","hours":1,"createdDate":"2023-03-10T21:06:32.226Z","updatedDate":"2024-03-05T03:27:43.244Z","videoConferenceLink":"https://us02web.zoom.us/j/83834020199?pwd=em9sSy9jdit5RTRHQWZ3NFNGUVg4Zz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640bb91afad84600219def22","name":"PM/Org","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"6407cb7ce587a20020ebcec6","name":"Tables","projectStatus":"Active","createdDate":"2023-03-07T23:40:44.377Z","__v":0,"hflaWebsiteUrl":"","githubUrl":"https://github.com/hackforla/tables-public","description":"Google Tables team","githubIdentifier":"667629052","googleDriveUrl":"https://drive.google.com/drive/folders/0AO5HWG9daZAtUk9PVA","slackUrl":"https://hackforla.slack.com/archives/C02LPQXUWJ0"},"date":"2024-04-18T22:00:00.554Z","startTime":"2024-04-18T22:00:00.554Z","endTime":"2024-04-18T23:00:00.554Z","hours":1,"createdDate":"2023-03-10T23:11:21.610Z","updatedDate":"2024-04-18T22:37:09.554Z","videoConferenceLink":"https://us06web.zoom.us/j/81993508851?pwd=lqU6D6CR7acb5D5zFmYEh4cEc2RRIg.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"640fd959b0b3a80020cd7bac","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["TBD"],"managedByUsers":[],"_id":"5edeac78ce228b001778facd","name":"VRMS","description":"VRMS is a tool used for the engagement, support, and retention of a network of volunteers.","githubIdentifier":"226157870","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/VRMS","slackUrl":"https://hackforla.slack.com/archives/CRGH5HM0Q","googleDriveUrl":"https://drive.google.com/drive/folders/1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","googleDriveId":"1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","hflaWebsiteUrl":"https://www.hackforla.org/projects/vrms","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- Front end devs (any level) \n - Back end devs (any level)","createdDate":"2020-06-08T21:24:08.313Z","__v":0},"date":"2024-03-26T02:00:00.443Z","startTime":"2024-03-26T02:00:00.443Z","endTime":"2024-03-26T03:00:00.443Z","hours":1,"createdDate":"2023-03-14T02:18:01.153Z","updatedDate":"2024-03-22T19:34:43.443Z","videoConferenceLink":"https://us06web.zoom.us/j/89075274719?pwd=QlZkMUtzZnRwbUczR3VwRnFjdzdHZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6419115a52db6500200a1f84","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/0AKWbU6_2dvZuUk9PVA","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"date":"2024-03-10T16:00:00.838Z","startTime":"2024-03-10T16:00:00.838Z","endTime":"2024-03-10T17:00:00.838Z","hours":1,"createdDate":"2023-03-21T02:07:22.782Z","updatedDate":"2024-03-05T03:34:32.838Z","videoConferenceLink":"https://us02web.zoom.us/j/82177492860?pwd=UGNYdmJXMXgvVmZiSGtETTR4VGV6Zz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6419f6c13f2c51001fb2a1c2","name":"Dev Leads/PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["N/A"],"managedByUsers":[],"_id":"5edeb146ce228b001778fad0","name":"Hack for LA Site","description":"The hackforla.org website is our organization's way of communicating with new volunteers, stakeholders, and donors. This project is a good place to start for new volunteers looking to polish their git protocol skills.","githubIdentifier":"130000551","projectStatus":"Active","location":"Westside, DTLA","githubUrl":"https://github.com/hackforla/website","slackUrl":"https://hackforla.slack.com/archives/C4UM52W93","googleDriveUrl":"https://drive.google.com/drive/folders/0AKWbU6_2dvZuUk9PVA","googleDriveId":"1p76K0FgfiAWeIIEyoyJ_Iik8FVj8cBjT","hflaWebsiteUrl":"https://www.hackforla.org/projects/website","videoConferenceLink":"https://zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (wireframes) \n - Photoshop \n - Junior JavaScript developers \n - anyone wanting to learn how to do Git commits in a collaborative work environment","createdDate":"2020-06-08T21:44:38.303Z","__v":0},"date":"2024-03-05T01:00:00.964Z","startTime":"2024-03-05T01:00:00.964Z","endTime":"2024-03-05T03:00:00.964Z","hours":2,"createdDate":"2023-03-21T18:26:11.199Z","updatedDate":"2024-03-05T03:34:30.964Z","videoConferenceLink":"https://us06web.zoom.us/j/89011346147?pwd=R280emlKVnRtTmF3RURrWFZ2d21zQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b667ba403830020e638db","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Code for America (CfA)","CfA National Advisory Council","Code for Boston","Code for Charlottesville"],"managedByUsers":[],"_id":"6086fe5792e3bf053b2954c4","name":"BOP","description":"This project aims to improve existing structures and create new ones that make it easier to share replicable processes and practices so that organizers and members can iterate on each others work, improving outcomes for the whole network.","githubIdentifier":"277577906","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/codeforamerica/brigade-playbook","slackUrl":"https://cfa.slack.com/archives/G0196272BBN","googleDriveUrl":"https://drive.google.com/drive/folders/0AHm1jtnPQgtkUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/brigade-organizers-playbook","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-08-19T00:00:00.000Z","__v":0},"date":"2024-03-05T17:00:00.259Z","startTime":"2024-03-05T17:00:00.259Z","endTime":"2024-03-05T18:00:00.259Z","hours":1,"createdDate":"2023-03-22T20:35:07.228Z","updatedDate":"2024-03-05T03:27:06.259Z","videoConferenceLink":"https://codeforamerica.zoom.us/j/98602227448?pwd=dVgyeld1dXBjbWlBaUQ5RzU5UkVpdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b66b9a403830020e638dc","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Code for America (CfA)","CfA National Advisory Council","Code for Boston","Code for Charlottesville"],"managedByUsers":[],"_id":"6086fe5792e3bf053b2954c4","name":"BOP","description":"This project aims to improve existing structures and create new ones that make it easier to share replicable processes and practices so that organizers and members can iterate on each others work, improving outcomes for the whole network.","githubIdentifier":"277577906","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/codeforamerica/brigade-playbook","slackUrl":"https://cfa.slack.com/archives/G0196272BBN","googleDriveUrl":"https://drive.google.com/drive/folders/0AHm1jtnPQgtkUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/brigade-organizers-playbook","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-08-19T00:00:00.000Z","__v":0},"date":"2024-03-10T15:00:00.584Z","startTime":"2024-03-10T15:00:00.584Z","endTime":"2024-03-10T16:00:00.584Z","hours":1,"createdDate":"2023-03-22T20:36:09.917Z","updatedDate":"2024-03-05T03:27:07.584Z","videoConferenceLink":"https://us02web.zoom.us/j/83945450679?pwd=VGY4QXNPMjRidTVKZERpVjduNVJXdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b684ca403830020e638dd","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"603e8471b6e1b403ab81abe7","name":"Community of Practice: Product Management","description":"A place for leads to communicate with each other and with the leadership team.","githubIdentifier":"275042633","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/product-management","slackUrl":"https://hackforla.slack.com/archives/C010LNXH2JY","googleDriveUrl":"https://drive.google.com/drive/folders/0AISloPaWXy2RUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"https://us02web.zoom.us/j/81435536017?pwd=eHNtNm5SVnpickxqUHRlbFJtS2tJUT09","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2024-03-08T20:00:00.396Z","startTime":"2024-03-08T20:00:00.396Z","endTime":"2024-03-08T21:00:00.396Z","hours":1,"createdDate":"2023-03-22T20:42:52.454Z","updatedDate":"2024-03-05T03:28:19.396Z","videoConferenceLink":"https://us02web.zoom.us/j/83795143399?pwd=QnJQdG8vSmhocG5FQXBEVGVrSUx4UT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b7681343d38001f81d1c9","name":"Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-09-18T02:30:00.419Z","startTime":"2024-09-18T02:30:00.419Z","endTime":"2024-09-18T03:30:00.419Z","hours":1,"createdDate":"2023-03-22T21:43:29.342Z","updatedDate":"2024-09-13T17:59:22.419Z","videoConferenceLink":"https://meet.google.com/cgn-yvmt-zge","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b9551cdea2c001e0df377","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-09-18T00:30:00.611Z","startTime":"2024-09-18T00:30:00.611Z","endTime":"2024-09-18T01:30:00.611Z","hours":1,"createdDate":"2023-03-22T23:54:56.667Z","updatedDate":"2024-09-13T18:04:18.611Z","videoConferenceLink":"https://meet.google.com/jcs-jpmy-grv","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b95becdea2c001e0df378","name":"Leads/PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-09-20T01:00:00.236Z","startTime":"2024-09-20T01:00:00.236Z","endTime":"2024-09-20T02:00:00.236Z","hours":1,"createdDate":"2023-03-22T23:56:46.052Z","updatedDate":"2024-09-13T18:05:41.236Z","videoConferenceLink":"https://us06web.zoom.us/j/88320911998?pwd=cFViOUorSHNxbDUrL29XcDFScWJidz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"641b964bcdea2c001e0df379","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"Once a month","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-09-20T01:00:00.733Z","startTime":"2024-09-20T01:00:00.733Z","endTime":"2024-09-20T02:00:00.733Z","hours":1,"createdDate":"2023-03-22T23:59:07.197Z","updatedDate":"2024-09-13T18:07:49.733Z","videoConferenceLink":"https://us06web.zoom.us/j/88320911998?pwd=cFViOUorSHNxbDUrL29XcDFScWJidz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64397c32f15295001f3ae51c","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6a98b87ed80001942b10a","name":"Guides Team","projectStatus":"Active","createdDate":"2023-01-29T17:14:51.760Z","__v":0,"description":"Creating guides and templates from the effective practices that HfLA has developed and iterated from our projects. HfLA Guides aim to share replicable processes and practices from Engineering, UI/UX, Product Management, Data Science, Marketing Fundraising, DevOps, Admin, and Professional Development. The project seeks to further grow HfLA’s peer learning and iterative culture, and ultimately improve outcomes for the entire civic tech ecosystem.","githubUrl":"https://github.com/hackforla/guides","slackUrl":"https://hackforla.slack.com/archives/C028T9XU9S5","hflaWebsiteUrl":"https://www.hackforla.org/projects/guides-team","githubIdentifier":"386323061","googleDriveUrl":"https://drive.google.com/drive/folders/0AOyia66xiVyGUk9PVA","location":"https://us06web.zoom.us/j/85331955066?pwd=35naUwc1pLrvcQdBEwlTMPQZafcH9d.1"},"date":"2024-03-08T15:30:00.270Z","startTime":"2024-03-08T15:30:00.270Z","endTime":"2024-03-08T17:00:00.270Z","hours":1.5,"createdDate":"2023-04-14T16:15:46.025Z","updatedDate":"2024-03-05T03:32:39.270Z","videoConferenceLink":"https://us02web.zoom.us/j/84639292835?pwd=eG1DNUVuTEZPbVp4VjhQeWQ4MVkvZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"645fcd889057b4001d20cf35","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2024-03-07T03:00:00.525Z","startTime":"2024-03-07T03:00:00.525Z","endTime":"2024-03-07T04:00:00.525Z","hours":1,"createdDate":"2023-05-13T17:48:56.369Z","updatedDate":"2024-03-05T03:33:35.525Z","videoConferenceLink":"https://us02web.zoom.us/j/81644568036?pwd=RllXN3RzaTFpTHJIeU4wNGo4TS9WUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"645fce729057b4001d20cf36","name":"Stakeholder Prep","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2024-03-07T21:00:00.393Z","startTime":"2024-03-07T21:00:00.393Z","endTime":"2024-03-07T22:00:00.393Z","hours":1,"createdDate":"2023-05-13T17:52:49.824Z","updatedDate":"2024-03-05T03:33:37.393Z","videoConferenceLink":"https://us02web.zoom.us/j/83270067282?pwd=dnhVelQ2YnFUcmhXSEhUL0tuUURXQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64922028841c83002296b2e3","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["TBD"],"managedByUsers":[],"_id":"5edeac78ce228b001778facd","name":"VRMS","description":"VRMS is a tool used for the engagement, support, and retention of a network of volunteers.","githubIdentifier":"226157870","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/VRMS","slackUrl":"https://hackforla.slack.com/archives/CRGH5HM0Q","googleDriveUrl":"https://drive.google.com/drive/folders/1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","googleDriveId":"1uxCkpcPtDjrhftBO-axU2g8hjXsxiLiS","hflaWebsiteUrl":"https://www.hackforla.org/projects/vrms","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- Front end devs (any level) \n - Back end devs (any level)","createdDate":"2020-06-08T21:24:08.313Z","__v":0},"date":"2024-06-06T23:00:00.827Z","startTime":"2024-06-06T23:00:00.827Z","endTime":"2024-06-07T00:00:00.827Z","hours":1,"createdDate":"2023-06-20T21:54:48.403Z","updatedDate":"2024-06-04T01:40:09.827Z","videoConferenceLink":"https://us06web.zoom.us/j/83685103472?pwd=VGpXaWJLWEh5aDlTWVRycVZmZ1V5Zz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6495f032a2eeb0002020688f","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2024-03-07T03:00:00.849Z","startTime":"2024-03-07T03:00:00.849Z","endTime":"2024-03-07T04:00:00.849Z","hours":1,"createdDate":"2023-06-23T19:19:14.214Z","updatedDate":"2024-03-05T03:26:28.849Z","videoConferenceLink":"https://us06web.zoom.us/j/83626721699?pwd=VUhITjRyY2FTQzRhc0NwRnFOREJDdz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64961cd3a75c2c0020ae4f87","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"1st week","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2024-03-07T03:00:00.113Z","startTime":"2024-03-07T03:00:00.113Z","endTime":"2024-03-07T04:00:00.113Z","hours":1,"createdDate":"2023-06-23T22:29:38.825Z","updatedDate":"2024-03-05T03:26:31.113Z","videoConferenceLink":"https://us06web.zoom.us/j/82617071267?pwd=bEFmOVZYTDREanhGbjZQOFdWR0NxUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bc1bbc4f7f0027f23e32","name":"Dev","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-09-17T03:00:00.786Z","startTime":"2024-09-17T03:00:00.786Z","endTime":"2024-09-17T03:30:00.786Z","hours":1,"createdDate":"2023-06-26T16:26:03.554Z","updatedDate":"2024-09-12T16:49:54.786Z","videoConferenceLink":"https://us06web.zoom.us/j/88240854525?pwd=6qZ9TF6303MqYGCb8a3FbRVPxJvVpj.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bc75bc4f7f0027f23e33","name":"Content","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-09-12T19:00:00.056Z","startTime":"2024-09-12T19:00:00.056Z","endTime":"2024-09-12T20:00:00.056Z","hours":1,"createdDate":"2023-06-26T16:27:33.676Z","updatedDate":"2024-09-08T20:19:48.056Z","videoConferenceLink":"https://us06web.zoom.us/j/85133711993?pwd=VSrI2qW0akve2AbbaWmGHTaZJgSbmf.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499bce7bc4f7f0027f23e35","name":"Research","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-10-14T22:00:00.981Z","startTime":"2024-10-14T22:00:00.981Z","endTime":"2024-10-14T23:00:00.981Z","hours":1,"createdDate":"2023-06-26T16:29:27.456Z","updatedDate":"2024-10-11T19:04:01.981Z","videoConferenceLink":"https://us02web.zoom.us/j/86353515192?pwd=VHRDOWFlZCtwOFNrdGpQdUk5R2YzUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6499be26c0de5700203a5510","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"1st Friday of the month is Leads/PMs only for planning.","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-10-11T17:30:00.427Z","startTime":"2024-10-11T17:30:00.427Z","endTime":"2024-10-11T18:30:00.427Z","hours":1,"createdDate":"2023-06-26T16:34:46.085Z","updatedDate":"2024-10-11T21:28:42.427Z","videoConferenceLink":"https://us06web.zoom.us/j/84526661131?pwd=eDBOY2Nnejh1VmJRTGY2N09lenNhZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64da4c5a21bb24002091e958","name":"PM/Org","hacknight":"Online","eventType":"Team Meeting","description":"First Friday of the month","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"5edeab95ce228b001778facc","name":"Expunge Assist","description":"Expunge Assist helps people in California with non-violent criminal records accomplish record clearance, expungement or reduction as a result of Prop 47 & Prop 64. The main features include building trust, educating the public about the program and informing those who are eligible for this program.","githubIdentifier":"218391110","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/expunge-assist","slackUrl":"https://hackforla.slack.com/archives/CN8NXTPK5","googleDriveUrl":"https://drive.google.com/drive/folders/1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","googleDriveId":"1hBhOeNyjjEaHcWAKSu9eW--FF9HnKNqe","hflaWebsiteUrl":"https://www.hackforla.org/projects/expunge-assist","videoConferenceLink":"https://meet.google.com/xwk-mqos-ecf","lookingDescription":"- Research/UX-UI","createdDate":"2020-06-08T21:20:21.619Z","__v":0},"date":"2024-10-11T20:00:00.846Z","startTime":"2024-10-11T20:00:00.846Z","endTime":"2024-10-11T21:00:00.846Z","hours":1,"createdDate":"2023-08-14T15:46:35.918Z","updatedDate":"2024-10-11T21:29:41.846Z","videoConferenceLink":"https://us02web.zoom.us/j/83738091907?pwd=VjBqY1Q3aTRkUmJISkxDaXprK29xQT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64da4cf321bb24002091e959","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"6407cb7ce587a20020ebcec6","name":"Tables","projectStatus":"Active","createdDate":"2023-03-07T23:40:44.377Z","__v":0,"hflaWebsiteUrl":"","githubUrl":"https://github.com/hackforla/tables-public","description":"Google Tables team","githubIdentifier":"667629052","googleDriveUrl":"https://drive.google.com/drive/folders/0AO5HWG9daZAtUk9PVA","slackUrl":"https://hackforla.slack.com/archives/C02LPQXUWJ0"},"date":"2024-04-24T21:30:00.434Z","startTime":"2024-04-24T21:30:00.434Z","endTime":"2024-04-24T22:30:00.434Z","hours":1,"createdDate":"2023-08-14T15:49:09.766Z","updatedDate":"2024-04-18T22:37:35.434Z","videoConferenceLink":"https://us06web.zoom.us/j/87937582522?pwd=oDMtMY5q25Qs4oZgm59mFzVn2cpp5v.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64eea5136b9ee100206f94b5","name":"UX Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"297491982","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMdnUkSXicNCUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-09-07T00:00:00.134Z","startTime":"2024-09-07T00:00:00.134Z","endTime":"2024-09-07T01:00:00.134Z","hours":1,"createdDate":"2023-08-30T02:10:26.880Z","updatedDate":"2024-09-05T03:51:04.134Z","videoConferenceLink":"https://us06web.zoom.us/j/89830222516","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f73b6296eab500228642b8","name":"PM","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2024-03-08T03:00:00.342Z","startTime":"2024-03-08T03:00:00.342Z","endTime":"2024-03-08T04:00:00.342Z","hours":1,"createdDate":"2023-09-05T14:30:05.578Z","updatedDate":"2024-03-05T03:26:33.342Z","videoConferenceLink":"https://us06web.zoom.us/j/87979035538?pwd=ZGtiU1FJeTN0V3BFNXYyMDYvN08yUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f740837211620022f7757e","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"64f740007211620022f7757d","name":"Community of Practice: CoP Leads","description":"The Leads Meeting for All the CoPs","location":"https://us02web.zoom.us/s/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","githubUrl":"https://github.com/hackforla/communities-of-practice","slackUrl":"https://hackforla.slack.com/archives/C026UMZK89X","googleDriveUrl":"https://drive.google.com/drive/folders/0AHDu27vDmN91Uk9PVA","projectStatus":"Active","createdDate":"2023-09-05T14:49:36.374Z","__v":0,"githubIdentifier":"337874660","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice"},"date":"2024-03-07T02:00:00.688Z","startTime":"2024-03-07T02:00:00.688Z","endTime":"2024-03-07T03:00:00.688Z","hours":1,"createdDate":"2023-09-05T14:51:58.752Z","updatedDate":"2024-03-05T03:27:49.688Z","videoConferenceLink":"https://us02web.zoom.us/j/86196694131?pwd=YVpCR1NWa0s4RmhkcjQ1cFdQSFZiUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f74653dfa4320020688749","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"605772bb46b7cd034719d114","name":"Community of Practice: Software Engineering","description":"Community of Practice for Software Engineers","githubIdentifier":"328256372","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/engineering","slackUrl":"https://hackforla.slack.com/archives/C01CU709SER","googleDriveUrl":"https://drive.google.com/drive/folders/0ALZlGXAx55mQUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/communities-of-practice","videoConferenceLink":"","lookingDescription":"","createdDate":"2021-03-01T19:42:22.028Z","__v":0},"date":"2024-03-11T02:00:00.609Z","startTime":"2024-03-11T02:00:00.609Z","endTime":"2024-03-11T02:30:00.609Z","hours":0.5,"createdDate":"2023-09-05T15:16:46.959Z","updatedDate":"2024-03-05T03:28:28.609Z","videoConferenceLink":"https://us06web.zoom.us/j/88450399932?pwd=NUpMeGM2ZS85VWp4b3QwbUtTT0FCZz09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"64f76e2574597c0020feef75","name":"Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63d6ac0987ed80001942b10b","name":"Tech Work Experience","projectStatus":"Active","createdDate":"2023-01-29T17:25:29.692Z","__v":0,"hflaWebsiteUrl":"https://www.hackforla.org/projects/tech-work-experience","description":"The Tech Work Experience project is a structured summer internship program for college and high school students to work on open source projects in the fields of software, product development, project management, and UI/UX design","githubIdentifier":"376872876","githubUrl":"https://github.com/hackforla/internship","googleDriveUrl":"https://drive.google.com/drive/folders/0ACgRrPVkhnrvUk9PVA","slackUrl":"https://github.com/hackforla/internship"},"date":"2024-03-05T20:30:00.612Z","startTime":"2024-03-05T20:30:00.612Z","endTime":"2024-03-05T21:00:00.612Z","hours":0.5,"createdDate":"2023-09-05T18:06:40.942Z","updatedDate":"2024-03-05T03:27:47.612Z","videoConferenceLink":"https://us06web.zoom.us/j/89505679972?pwd=c0QzS1JFQkxoZGdYaU16VmdzcEhXUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6503252a26c03f00229adaf0","name":"All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0,"description":"HfLA admin team.","githubIdentifier":"380865495","githubUrl":"https://github.com/hackforla/admin","googleDriveUrl":"https://drive.google.com/drive/folders/0AMjgqUp9AI13Uk9PVA","hflaWebsiteUrl":"","slackUrl":"https://hackforla.slack.com/archives/C01Q24YF56J"},"date":"2024-03-06T20:00:00.003Z","startTime":"2024-03-06T20:00:00.003Z","endTime":"2024-03-06T21:00:00.003Z","hours":1,"createdDate":"2023-09-14T15:22:20.053Z","updatedDate":"2024-03-05T03:26:49.003Z","videoConferenceLink":"https://us06web.zoom.us/j/89741924912?pwd=bqSrHEszyfv6p90SmOt66vCDLuz5ol.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6503257c26c03f00229adaf1","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0,"description":"HfLA admin team.","githubIdentifier":"380865495","githubUrl":"https://github.com/hackforla/admin","googleDriveUrl":"https://drive.google.com/drive/folders/0AMjgqUp9AI13Uk9PVA","hflaWebsiteUrl":"","slackUrl":"https://hackforla.slack.com/archives/C01Q24YF56J"},"date":"2024-03-04T15:00:00.431Z","startTime":"2024-03-04T15:00:00.431Z","endTime":"2024-03-04T18:00:00.431Z","hours":3,"createdDate":"2023-09-14T15:23:42.935Z","updatedDate":"2024-03-05T03:26:52.431Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6503259826c03f00229adaf2","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0,"description":"HfLA admin team.","githubIdentifier":"380865495","githubUrl":"https://github.com/hackforla/admin","googleDriveUrl":"https://drive.google.com/drive/folders/0AMjgqUp9AI13Uk9PVA","hflaWebsiteUrl":"","slackUrl":"https://hackforla.slack.com/archives/C01Q24YF56J"},"date":"2024-03-05T15:00:00.715Z","startTime":"2024-03-05T15:00:00.715Z","endTime":"2024-03-05T18:00:00.715Z","hours":3,"createdDate":"2023-09-14T15:24:10.280Z","updatedDate":"2024-03-05T03:26:50.715Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"650325ae26c03f00229adaf3","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0,"description":"HfLA admin team.","githubIdentifier":"380865495","githubUrl":"https://github.com/hackforla/admin","googleDriveUrl":"https://drive.google.com/drive/folders/0AMjgqUp9AI13Uk9PVA","hflaWebsiteUrl":"","slackUrl":"https://hackforla.slack.com/archives/C01Q24YF56J"},"date":"2024-03-06T15:00:00.544Z","startTime":"2024-03-06T15:00:00.544Z","endTime":"2024-03-06T18:00:00.544Z","hours":3,"createdDate":"2023-09-14T15:24:32.771Z","updatedDate":"2024-03-05T03:26:47.544Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"650325d226c03f00229adaf4","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0,"description":"HfLA admin team.","githubIdentifier":"380865495","githubUrl":"https://github.com/hackforla/admin","googleDriveUrl":"https://drive.google.com/drive/folders/0AMjgqUp9AI13Uk9PVA","hflaWebsiteUrl":"","slackUrl":"https://hackforla.slack.com/archives/C01Q24YF56J"},"date":"2024-03-07T15:00:00.205Z","startTime":"2024-03-07T15:00:00.205Z","endTime":"2024-03-07T18:00:00.205Z","hours":3,"createdDate":"2023-09-14T15:25:08.160Z","updatedDate":"2024-03-05T03:26:46.205Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"650325e726c03f00229adaf5","name":"Special Projects All","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":[],"managedByUsers":[],"_id":"63de906b87ed80001942b1fe","name":"Admin team","projectStatus":"Active","createdDate":"2023-02-04T17:05:47.198Z","__v":0,"description":"HfLA admin team.","githubIdentifier":"380865495","githubUrl":"https://github.com/hackforla/admin","googleDriveUrl":"https://drive.google.com/drive/folders/0AMjgqUp9AI13Uk9PVA","hflaWebsiteUrl":"","slackUrl":"https://hackforla.slack.com/archives/C01Q24YF56J"},"date":"2024-03-08T15:00:00.618Z","startTime":"2024-03-08T15:00:00.618Z","endTime":"2024-03-08T18:00:00.618Z","hours":3,"createdDate":"2023-09-14T15:25:29.505Z","updatedDate":"2024-03-05T03:26:44.618Z","videoConferenceLink":"https://us06web.zoom.us/j/81345944648?pwd=cDI5WFl6aFE4ZXRSU252ck5ZRC8zUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"6514d16f609cb4002070f9b4","name":"Test-EventName","hacknight":"Online","eventType":"Team Meeting","description":"Testing","project":{"recruitingCategories":[],"partners":["Josh"],"managedByUsers":["Josh"],"_id":"644748563212e6001fbca24a","name":"Testing","description":"testy","location":"www.test.com","githubUrl":"updated_github_address.com","slackUrl":"updated_slack_channel.com","googleDriveUrl":"updated_google_drive.com","projectStatus":"Active","createdDate":"2023-04-25T03:26:14.482Z","__v":0,"githubIdentifier":"Spiteless","hflaWebsiteUrl":"updated_website.com/test34","googleDriveId":"update_google_drive_id23"},"date":"2024-03-07T06:00:00.383Z","startTime":"2024-03-07T06:00:00.383Z","endTime":"2024-03-07T07:00:00.383Z","hours":1,"createdDate":"2023-09-28T01:05:51.900Z","updatedDate":"2024-03-05T03:27:26.383Z","videoConferenceLink":"example.com","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"65665b6ae1a41b0022515eca","name":"Leads","hacknight":"Online","eventType":"Team Meeting","description":"1st week","project":{"recruitingCategories":[],"partners":[""],"managedByUsers":[],"_id":"620997442720480f934e4362","name":"Civic Tech Jobs","description":"The CivicTechJobs.org MVP website will be a platform to help prospective volunteers find projects that will be useful for their career development.","githubIdentifier":"297491982","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/CivicTechJobs","slackUrl":"https://hackforla.slack.com/messages/C02509WHFQQ","googleDriveUrl":"https://drive.google.com/drive/folders/0AMdnUkSXicNCUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/civic-tech-jobs","videoConferenceLink":"https://us02web.zoom.us/j/81515187819?pwd=UzF1YjFwcnhNaTBtV3hyMHgyKzhpdz09","lookingDescription":"","createdDate":"2022-02-13T00:22:31.295Z","__v":0},"date":"2024-03-06T01:00:00.113Z","startTime":"2024-03-06T01:00:00.113Z","endTime":"2024-03-06T02:00:00.113Z","hours":1,"createdDate":"2023-11-28T21:28:10.060Z","updatedDate":"2024-03-05T03:27:29.113Z","videoConferenceLink":"https://us06web.zoom.us/j/84729938240?pwd=YlBOd21vbE5PcVhHWTNObk05NlBrUT09","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"65aecebd5530fe0025f9dad7","name":"Design/Data","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Code for America (CfA)","CfA National Advisory Council","Code for Boston","Code for Charlottesville"],"managedByUsers":[],"_id":"6086fe5792e3bf053b2954c4","name":"BOP","description":"This project aims to improve existing structures and create new ones that make it easier to share replicable processes and practices so that organizers and members can iterate on each others work, improving outcomes for the whole network.","githubIdentifier":"277577906","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/codeforamerica/brigade-playbook","slackUrl":"https://cfa.slack.com/archives/G0196272BBN","googleDriveUrl":"https://drive.google.com/drive/folders/0AHm1jtnPQgtkUk9PVA","googleDriveId":"","hflaWebsiteUrl":"https://www.hackforla.org/projects/brigade-organizers-playbook","videoConferenceLink":"","lookingDescription":"","createdDate":"2020-08-19T00:00:00.000Z","__v":0},"date":"2024-03-08T16:00:00.018Z","startTime":"2024-03-08T16:00:00.018Z","endTime":"2024-03-08T16:30:00.018Z","hours":0.5,"createdDate":"2024-01-22T20:23:24.845Z","updatedDate":"2024-03-05T03:27:05.018Z","videoConferenceLink":"https://us04web.zoom.us/j/2206070789?pwd=qCs2uCfM4LZeih3tbtfNeI4cqsVDZH.1&omn=79894920171","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"66bd7afabbac790023b8f880","name":"Design ","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2024-08-15T01:00:00.605Z","startTime":"2024-08-15T01:00:00.605Z","endTime":"2024-08-15T02:00:00.605Z","hours":1,"createdDate":"2024-08-15T03:50:19.605Z","updatedDate":"2024-08-15T03:50:19.605Z","videoConferenceLink":"https://meet.google.com/gye-vohy-vfd?authuser=1&hs=122","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"66c7880be5b4960026317a0f","name":"Dev","hacknight":"Online","eventType":"Team Meeting","description":"Reviewing open tickets and diving into codebase","project":{"recruitingCategories":[],"partners":["EmpowerLA"],"managedByUsers":[],"_id":"5eb9e2de3409ffef8194ffde","name":"311 Data","description":"The 311 Data project seeks to empower local Neighborhood Councils to improve the ideation and analysis of their initiatives using the wealth of publicly available 311 data.","githubIdentifier":"190321758","projectStatus":"Active","location":"Remote","githubUrl":"https://github.com/hackforla/311-data","slackUrl":"https://hackforla.slack.com/archives/CJY4R382X","googleDriveUrl":"https://drive.google.com/drive/u/0/folders/10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","googleDriveId":"10_KYe3pbZqiq6reeLA8zDDeIlz-4PxWM","hflaWebsiteUrl":"https://www.hackforla.org/projects/311-data","videoConferenceLink":"https://us04web.zoom.us/j/8358875318","lookingDescription":"Frontend Developers, Backend Developers, Backend Lead, DevOps","createdDate":"2020-05-11T23:42:22.028Z","__v":0},"date":"2024-08-24T17:00:00.863Z","startTime":"2024-08-24T17:00:00.863Z","endTime":"2024-08-24T18:00:00.863Z","hours":1,"createdDate":"2024-08-22T18:48:42.863Z","updatedDate":"2024-08-22T18:48:42.863Z","videoConferenceLink":"https://us06web.zoom.us/j/83511601337?pwd=VkqPEjI11WlNdCdqXuWXZeh3oVQgY6.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"66e35bb45d07d5002bee745f","name":"Dev","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2024-09-19T01:30:00.475Z","startTime":"2024-09-19T01:30:00.475Z","endTime":"2024-09-19T02:00:00.475Z","hours":0.5,"createdDate":"2024-09-12T21:23:00.475Z","updatedDate":"2024-09-12T21:23:00.475Z","videoConferenceLink":"https://us06web.zoom.us/j/88173352545?pwd=tZCYGlspHNqmPfO1NmIWODs1qwvJzu.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"66e35c045d07d5002bee7460","name":"Stakeholder followup","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2024-09-18T00:00:00.482Z","startTime":"2024-09-18T00:00:00.482Z","endTime":"2024-09-18T01:00:00.482Z","hours":1,"createdDate":"2024-09-12T21:24:20.482Z","updatedDate":"2024-09-12T21:24:20.482Z","videoConferenceLink":"https://us06web.zoom.us/j/82635608437?pwd=8IKU4sGDPbRIDqaZgCEMtpoCrb2Agk.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"66e47fabf05a80002a77fbe5","name":"UXR","hacknight":"Online","eventType":"Team Meeting","description":"Twice a month","project":{"recruitingCategories":[],"partners":["Seeking"],"managedByUsers":[],"_id":"5edea7d2ce228b001778fac9","name":"Food Oasis","description":"The website is focused on individuals seeking food in Los Angeles who need an up-to-date resource about food pantries and meals. Our mission is to update the existing website, foodoasis.la with a simplified UI and verified data. Future development goals include creating functionality for referral services that will allow the end user to annotate and update listings through a peer verification system.","githubIdentifier":"215666884","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/foodoasisla","slackUrl":"https://hackforla.slack.com/archives/C6JBH478W","googleDriveUrl":"https://drive.google.com/drive/folders/1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","googleDriveId":"1nVn3v_kD9GJ2IO6A84DZkox9h1eqMeRO","hflaWebsiteUrl":"https://www.hackforla.org/projects/food-oasis","videoConferenceLink":"https://us02web.zoom.us/j/85496859954","lookingDescription":"- Project Management \n - Junior Python developers (2) \n - documentarian (UX) - specifically someone to help with the wiki for onboarding and communicating to stake holders what the project is about","createdDate":"2020-06-08T21:04:18.272Z","__v":0},"date":"2024-10-17T19:00:00.766Z","startTime":"2024-10-17T19:00:00.766Z","endTime":"2024-10-17T20:00:00.766Z","hours":1,"createdDate":"2024-09-13T18:08:42.327Z","updatedDate":"2024-10-17T23:21:29.766Z","videoConferenceLink":"https://us06web.zoom.us/j/86740231069?pwd=HIKRxLmyoBxyZDEcECsvjIwFrEzNbO.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"66ec9e18014fda0026aa6139","name":"Design","hacknight":"Online","eventType":"Team Meeting","description":"","project":{"recruitingCategories":[],"partners":["LA Department of Transportation LADOT (https://ladot.lacity.org/)"],"managedByUsers":[],"_id":"5edeb2face228b001778fad2","name":"LA TDM Calculator","description":"We’re building a TDM web calculator for LADOT. It scores proposed real estate developments in real-time and aims to discourage exceeding parking requirements to reduce the occurrence of single-occupancy trips to new developments.","githubIdentifier":"197452459","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/tdm-calculator","slackUrl":"https://hackforla.slack.com/archives/CKY65G266","googleDriveUrl":"https://drive.google.com/drive/folders/1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","googleDriveId":"1XI0ZP21DoNM8uTKVJkRBiMhtP652X8KM","hflaWebsiteUrl":"https://www.hackforla.org/projects/tdm-calculator","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI Designer","createdDate":"2020-06-08T21:51:54.904Z","__v":0},"date":"2024-09-26T01:30:00.808Z","startTime":"2024-09-26T01:30:00.808Z","endTime":"2024-09-26T02:00:00.808Z","hours":0.5,"createdDate":"2024-09-19T21:56:40.808Z","updatedDate":"2024-09-19T21:56:40.808Z","videoConferenceLink":"https://us06web.zoom.us/j/88173352545?pwd=tZCYGlspHNqmPfO1NmIWODs1qwvJzu.1","__v":0},{"location":{"city":"Los Angeles","state":"CA","country":"USA"},"owner":{"ownerId":"123456"},"brigade":"Hack for LA","checkInReady":false,"_id":"673c304e88564600280e4be4","name":"Research","hacknight":"Online","eventType":"Team Meeting","description":"Team Meeting","project":{"recruitingCategories":[],"partners":["Safe Place for Youth (SPY)"],"managedByUsers":[],"_id":"5edea961ce228b001778faca","name":"Home Unite Us","description":"We're working with community non-profits who have a Host Home initiative to develop a workflow management tool to make the process scaleable (across all providers), reduce institutional bias, and effectively capture data.

Host Home programs are centered around housing young people, 18 - 25 years old. Their approach focuses on low-cost, community-driven intervention by matching a willing host with a guest or group of guests, providing a stable housing environment for youths who are experiencing homelessness and seeking stable housing.","githubIdentifier":"228981080","projectStatus":"Active","location":"DTLA","githubUrl":"https://github.com/hackforla/homeuniteus","slackUrl":"https://hackforla.slack.com/archives/CRWUG7X0C","googleDriveUrl":"https://drive.google.com/drive/folders/1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","googleDriveId":"1ahxiD9rIsBtx0yAPlPcPaGw8zGrfHHm9","hflaWebsiteUrl":"https://www.hackforla.org/projects/home-unite-us","videoConferenceLink":"https://us02web.zoom.us/j/4451450308?pwd=U0JobzZqN0xGSXBUUkRsNlB5YzJiQT09","lookingDescription":"- UI (including wireframes, familiar with Figma) \n","createdDate":"2020-06-08T21:10:57.147Z","__v":0},"date":"2024-11-21T00:30:00.112Z","startTime":"2024-11-21T00:30:00.112Z","endTime":"2024-11-21T01:30:00.112Z","hours":1,"createdDate":"2024-11-19T06:29:34.112Z","updatedDate":"2024-11-19T06:29:34.112Z","videoConferenceLink":"https://meet.google.com/gye-vohy-vfd?authuser=2&hs=122","__v":0}] \ No newline at end of file diff --git a/_data/external/wins-data.json b/_data/external/wins-data.json index 1957a02c5f..816566f2de 100644 --- a/_data/external/wins-data.json +++ b/_data/external/wins-data.json @@ -1,2 +1 @@ -[["2020-08-16T04:55:40.174Z","paridox@hotmail.com","Dean Church","https://www.linkedin.com/in/deanchurch/","Yes","","No","VRMS","Business Analyst","Product Roadmap construction","2019-07-01T07:00:00.000Z","I worked on an enterprise project, I worked on a project that will help the people of Los Angeles","I took the skills I have learned from HackforLA projects and applied them at work to orchestrate the launch of an MVP to help with Wildfire Mitigation throughout Southern California",true,false],["2020-08-16T05:28:29.558Z","paridox@hotmail.com","Dean Church","https://www.linkedin.com/in/deanchurch/","Yes","","No","VRMS","Business Analyst","","2019-07-01T07:00:00.000Z","I got a new job","As an over 50 year old career changer I was amazed at how supportive the community at HackforLA was in my finding meaningful employment in the local tech industry. Through exposure and application of Agile frameworks and user centered design thinking my time and practice at HfLA was instrumental in building my modern application skills competency and confidence. A direct result of my time at HfLA is that I was able to ace my 45min White Boarding interview where I had to diagram a workflow from end to end and identify areas that would benefit from automation. ",true,false],["2020-09-02T23:56:13.840Z","jpbubar@gmail.com","Josh Bubar","https://www.linkedin.com/in/joshua-bubar-25331a118/","Yes","https://github.com/jbubar","Yes","HackforLA Website","Development","Frontend Web Development","","I produced something for my portfolio, I increased the number of commits on my Github profile","I built my first page for hack for la! and it is this one!!! ...the wins page",true,false],["2020-11-30T03:47:02.249Z","alexandrastubbs12@gmail.com","Alex Stubbs","http://linkedin.com/in/alexandrajstubbs","Yes","","No","HackforLA Website","PM","","2020-06-01T07:00:00.000Z","I got a new job","I got a job as a product manager! This is something I have been working towards for awhile and Hack for LA helped me build the skills to achieve it. ",true,false],["2020-11-30T06:17:25.226Z","johnsritchey@yahoo.com","John R","https://www.linkedin.com/in/johnsritchey/","Yes","","No","311 Data","PM","","2019-09-17T07:00:00.000Z","I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team, I taught or mentored a person on another team, My team delivered software to a stakeholder, My team launched our MVP","Hack for LA has given me the opportunity to make connections with the people of Los Angeles tech community and local government that I would not have otherwise made. It is a joy to build things that actually help our community with people that are all focused on solving critical community challenges.",true,false],["2020-11-30T20:16:27.451Z","itsevalieu@gmail.com","Eva Lieu","https://www.linkedin.com/in/eva-lieu/","Yes","","","Shared Housing","Development","","","I got a new job, I improved my LinkedIn, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles","I joined the Shared Housing project and made a lot of friends with great people who helped me improve my coding skills. I learned how to work better on a team and eventually got a new job through one of my newly found friends here at HackforLA. I also enjoyed working on a project that was meant to help the people of LA, and it motivated me to keep learning front end development skills. ",true,true],["2020-11-30T20:55:42.121Z","prashantsingh071993@gmail.com","Prashant Singh","https://www.linkedin.com/in/prashant07singh/","Yes","","","100Automations, Food Oasis, TDM Calculator","Operations","","2020-10-01T07:00:00.000Z","I got a new job, I improved my LinkedIn, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles","I am grateful to the Hackforla team to give me an opportunity to contribute to their work and do what I like to do the best",true,false],["2020-12-01T17:00:51.013Z","sam@greenhacks.org","Sam Miyamoto","https://www.linkedin.com/in/e-samantha-miyamoto/","Yes","https://github.com/greenhacks","No","311 Data, HelloGov","QA, UI/UX, Accessibility testing","","2019-06-19T07:00:00.000Z","I improved my LinkedIn, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, Found a mentor and became part of a caring tech community!","HfLA makes me feel like I'm a part of the community, and though I might not be as active as I'd like, this group provides immense comfort! I'm glad to be part of the team here.",true,true],["2020-12-01T17:14:19.883Z","jenny@foodoasis.la","Jenny Mikesell","https://www.linkedin.com/in/jenny-mikesell","Yes","","","Food Oasis","Operations, UI/UX","","2018-08-01T07:00:00.000Z","I worked on a project that will help the people of Los Angeles","Food Oasis has an average of 400 unique visitors a day. Our database in Los Angeles has over 1000 listings. Since April 2020, community volunteers have helped us verify over 750 listings. We have proven that 30% of pantries have closed. The Department of Public Health just asked for a copy of our database to share with their nutritionists. We created an API and forked foodoasis.net to included Northern California, Oregon, and Hawaii. ",true,false],["2020-12-04T00:20:00.683Z","jake.mensch@gmail.com","Jake Mensch","https://www.linkedin.com/in/jacob-mensch/","Yes","https://github.com/jmensch1","Yes","311 Data","Development","","2020-02-15T08:00:00.000Z","I learned how to work better on a team, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, My team launched our MVP","I met some great people and built some cool apps.",true,false],["2020-12-17T22:07:08.182Z","joshuazrobins@gmail.com","Josh Robins","https://www.linkedin.com/in/joshuazrobins","Yes","","No","Food Oasis, HackforLA Website, Railstats LA, Work for LA","Business Analyst, Content, Data, Development, PM, QA, UI/UX","","2016-05-10T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I learned a new language, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, My team delivered software to a stakeholder, My team launched our MVP, I joined the leadership team in 2017 and got the opportunity to invest back into the Hack for LA community by organizing teams, projects, and events","I came to Hack for LA in 2016 as a full-stack web developer and was part of the founding group of Food Oasis LA. I originally joined this community because I wanted to make the transition to Product Management and gain experience building projects for real-world needs. Eventually, I joined the leadership team and ran our Downtown LA hack nights from 2017 to 2019 before stepping back to focus on personal endeavors. ",true,false],["2020-12-21T19:41:43.053Z","tmalstead@codeforamerica.org","Timothy Malstead","https://www.linkedin.com/in/timmalstead/","Yes","https://github.com/timmalstead-cfa","Yes","Food Oasis, Home Unite Us, Not Today","Development","","2019-12-21T08:00:00.000Z","I got a new job","I have begun a community fellowship with Code for America! We will be working on ways to allow justice impacted people easier access to public resources.",true,false],["2020-12-24T03:23:37.075Z","j100892@gmail.com","Daniel Lee","https://www.linkedin.com/in/kipsbaydan/","Yes","","","Record Clearance Project","PM","","2020-09-28T07:00:00.000Z","I got a new job, My team launched our MVP","Hack for LA is where I really had my first hands-on exposure to civic technology. Bonnie Wolfe and Dean Church really helped me bring the record clearance project off the ground and we currently have a tech lead and a development team building designs that our design/research team worked on. I also got an offer for my first civic tech design position today and am grateful for Hack for LA playing an integral part of it. Shoutout to the Record Clearance team and for all the hard work over the past few months! ",true,false],["2021-04-06T16:13:30.983Z","codewilling@gmail.com","Sean Flores","http://www.linkedin.com/in/sean-flores","Yes","","","Civic Tech Index","Development","","2020-09-01T07:00:00.000Z","I got a new job, I learned how to work better on a team, I increased the number of commits on my Github profile, I learned a new language, I worked on a project that will help the people of Los Angeles, I found multiple mentors","I could never commit to contributing to open source. The fear of not knowing enough kept me from applying my skills and full of imposter syndrome, until I began volunteering for Hack for LA. In addition to being able to help my community, I also gained access to a treasure-trove of resources through my colleagues, and found mentors that would've been inaccessible otherwise. I can only describe my experience with Hack for LA as feeling very lucky and look forward to continuing to contributing in the future.",true,false],["2021-05-10T23:57:41.849Z","gothe.s@northeastern.edu","Sharwari Gothe","https://www.linkedin.com/in/sharwarigothe/","Yes","","","311 Data","Development","","2021-02-04T08:00:00.000Z","I got a new job","I got a job at TCS as a Software Developer.",true,false],["2021-05-30T17:32:19.549Z","avali4907@outlook.com","Ava Li","","","","","HackforLA Website","Development","","2021-04-21T07:00:00.000Z","I learned how to work better on a team","I created documentation for the HackForLA Website project and everyone on the team loved it! It feels very nice to receive affirmations of appreciation.",true,false],["2021-06-11T21:13:46.096Z","thomisfrank@gmail.com","Thomas Phillip Franklin II","https://www.linkedIn.com/in/thomisfrank","Yes","","","311 Data","UI/UX","","2020-04-01T07:00:00.000Z","I got a new job, I worked on a project that will help the people of Los Angeles","I joined hack4LA in April of 2020 right after graduating General Assembly it was my first design role outside of the boot camp. I was able to work on the 311 data project which is improving the lives of Angelinos. \n\nUsing that foundation I was able to get a few freelance positions and eventually transition to being in the first cohort of Amazon's User Experience Research and Design Apprenticeship. ",true,true],["2021-06-18T21:00:10.288Z","pvonhagen26@gmail.com","Paul von Hagen","https://www.linkedin.com/in/paulvonhagen26/","Yes","https://github.com/paulsvh","Yes","HackforLA Website","Development","","2021-03-15T07:00:00.000Z","I got a new job","Hack For LA gave me a great foundation in working with others in a shared codebase. Not only did my experience here help lead me to a new job, I truly enjoyed all of my interactions with everyone on the team. Special shout out to Josh Bubar for being so welcoming and always happy to help others.",true,true],["2021-07-02T19:34:18.130Z","atkendis@gmail.com","Adam Kendis","https://www.linkedin.com/in/adamkendis","No","https://github.com/adamkendis","Yes","311 Data","Development","","2020-01-01T08:00:00.000Z","I got a new job, I produced something for my portfolio, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles, My team launched our MVP","Hack for LA gave me valuable experience working with product, UI/UX, and data teams. I met some awesome people, learned a lot, and got a new job!",true,false],["2021-07-10T22:46:42.566Z","niven.prasad@gmail.com","Niven Prasad","https://www.linkedin.com/in/nivenprasad/","Yes","https://github.com/NivenPrasad","Yes","100Automations","PM","","2020-06-01T07:00:00.000Z","I got a new job","I recently joined joined Homebot as a full-time Technical Product Manager! I'm working with APIs, integrations, and automations - so grateful for all my experience at Hack for LA and for all the people I got to work with both in the 100 Automations project and across other projects (and still do occasionally). Feel free to reach out if you ever want to connect or share experiences!",true,false],["2021-07-28T17:15:35.150Z","experimentsinhonesty@gmail.com","Bonnie Wolfe","https://linkedin/in/BonnieAWolfe","Yes","https://github.com/experimentsinhonesty","Yes","100Automations, 311 Data, Civic Opportunity Project, Civic Tech Index, Engage, Food Oasis, HackforLA Website, Home Unite Us, Record Clearance Project, TDM Calculator, VRMS","Operations, PM, QA","","2018-10-28T07:00:00.000Z","I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I set up 2FA, I worked on an enterprise project, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team, I taught or mentored a person on another team, My team delivered software to a stakeholder, My team launched our MVP","I learned how to create an inclusive community and working environments where the there are not artificial boundaries to personal growth",true,false],["2021-08-20T06:42:45.341Z","jpbubar@gmail.com","Josh Bubar","https://www.linkedin.com/in/jbubar/","Yes","https://github.com/jbubar","Yes","HackforLA Website, VRMS","Development","","2019-09-19T07:00:00.000Z","I got a new job, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I taught or mentored a person on my team","I got my first JOB in tech!! I learned so much from contributing to Hack for LA and I will use all of it in my new job!",true,true],["2021-09-03T02:17:49.434Z","evanjyang4@gmail.com","Evan Yang","https://www.linkedin.com/in/evanjyang/","Yes","www.github.com/evanyang1","Yes","VRMS","Development","","2021-08-07T07:00:00.000Z","I got a new job","Got a contract software engineering job (through a 3rd party company) at Facebook! I'm excited, but the journey has just started, got a long way to go!",true,false],["2021-11-01T22:29:30.304Z","janieche1@gmail.com","Janie Chen","https://www.linkedin.com/in/janiechen09","Yes","","No","HackforLA Website","UI/UX","","2021-07-01T07:00:00.000Z","I got a new job","I landed my first full-time role as a Product Designer @ DocuSign! Working with the HfLA team helped build up my confidence as a designer in a structured and supportive environment. It’s a great opportunity to put what I’ve learned into practice and improve both my design and collaboration skills. ",true,true],["2021-11-05T18:42:20.543Z","senbasudhara@gmail.com","Basudhara Sen","https://www.linkedin.com/in/basudhara-sen-ph-d-718b042b/","Yes","https://github.com/Basu3040","No","HackforLA Website","UI/UX","UX Research Lead","2021-07-29T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I learned a new language","HfLA gave me a 360-degree view of the UX processes. I was transitioning from academia to UX and I got hands-on experience working with diverse stakeholders in an agile environment. I worked with great team members who were always willing to collaborate and on task. I am thankful to HfLA for this awesome opportunity and I strode with confidence in UX job interviews. I landed a job as a UX Researcher at Symplr.",true,true],["2021-12-07T00:56:25.788Z","myechoproject@gmail.com","Eric Cho","https://www.linkedin.com/in/echoechoecho/","Yes","","Yes","311 Data","PM","Product Manager","2021-09-06T07:00:00.000Z","I was admitted into an MBA program.","I was applying for an MBA program to help pivot my career into Product Management. The time I spent learning new skills and working with like-minded individuals played a significant role in building my applicant profile. ",true,true],["2022-01-07T04:13:50.643Z","chalimar@gmail.com","Chali Prasertsri Stoyanoff","https://www.linkedin.com/in/cprasertsri/","Yes","https://github.com/chalimar","Yes","Civic Tech Index, Youth Justice Nav","UI/UX","Lead UX Designer","2020-02-04T08:00:00.000Z","I got a new job, I produced something for my portfolio, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","My experience with Hack for LA helped me land a job offer for Lead Product Designer!\n\nIn joining HfLA, I was looking to work with cross-functional team members and launch products that empower users and communities. The overall experience has helped me improve my personal tenacity, confidence as a design leader, and ability to communicate effectively.\n\nHfLA has been an invaluable resource for me, and I am thankful for the colleagues, professional growth, and support I’ve gained along the way.",true,false],["2022-01-08T02:47:43.080Z","ahoang94@gmail.com","Anh Hoang","https://www.linkedin.com/in/anhhoang-design/","Yes","","","Design Systems, HackforLA Website","UI/UX","UX/UI Designer","2021-07-19T07:00:00.000Z","I got a new job, I learned how to work better on a team, I worked on two or more projects","Hack for LA was a great resume and experience booster as someone who had just graduated from a UX bootcamp but had minimal real-world experience in the field. Working on the HfLA website and Design Systems projects allowed me to collaborate with not only other designers but also researchers and developers, and I was fortunate enough to receive mentorship from PM Hana Stevenson, whose career advice was keen and invaluable. I can say with confidence that my work at HfLA, especially for the Design Systems team, helped me land my new role as Product Designer at Lumanu.",true,false],["2022-02-05T02:59:57.876Z","jonathan.ko523@gmail.com","Jonathan Ko","https://www.linkedin.com/in/jonathanko523/","Yes","https://github.com/Jonathanko52","No","TDM Calculator, VRMS","Development","Frontend","","I got a new job","Hack for LA allowed me to refine my ability to work with others, expand my knowledge regarding web development, and introduced me to peers and mentors who have been and continue to be invaluable resources to me. Thanks to this organization, I've found my first job as a software engineer!",true,false],["2022-02-16T03:18:44.711Z","swerdlowbenjamin@gmail.com","Ben Swerdlow","","","","","BallotNav, New Schools Today","Development, PM","","2019-04-30T07:00:00.000Z","I got into U Chicago!","I got into U Chicago!! The leadership skills that the Hack for LA team were integral to my acceptance!",true,false],["2022-03-11T20:01:02.689Z","tanzhouinfo@gmail.com","Tan Zhou","https://www.linkedin.com/in/tan-zhou/","Yes","https://github.com/tan-zhou","Yes","Brigade Organizer’s Playbook, Civic Opportunity Project","UI/UX","UX Researcher","2020-08-01T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I worked on two or more projects","My journey at Hack for LA got to be one of the most engaging and rewarding experience. I was able to improve in my area of interests working on projects that made a positive impact. I am proud to witness how the UX/UI community of practice has grown to connect and uplift people from such diverse backgrounds. Recommend it for anyone that's looking to get involved with the civic tech movement and improve their skills.",true,false],["2022-03-23T01:38:52.891Z","juliaa423@gmail.com","Julia Anderson","https://www.linkedin.com/in/julia-a-anderson/","Yes","","","Home Unite Us","UI/UX","","2020-08-01T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles","Hack for LA taught me that design can't be done in a vacuum. Collaborating, designing and iterating together helped set the foundation for the rest of my design career. I felt that my strengths as a writer and designer were actualized through my supportive team. Not only did I learn what it takes to make a design system, but I discovered how satisfying it can be to use technology for good. ",true,false],["2022-04-10T20:24:50.437Z","sydney.walcoff@gmail.com","Sydney Walcoff","https://www.linkedin.com/in/sydneywalcoff/","Yes","https://github.com/sydneywalcoff","Yes","Expunge Assist, HackforLA Website","Development","Frontend Developer","2021-11-29T08:00:00.000Z","I got a new job, I improved my LinkedIn, I increased the number of commits on my Github profile, I worked on a project that will help the people of Los Angeles, I taught or mentored a person on my team","Hack for LA is a great way to get hands-on experience while also working on projects to improve the lives of Angelenos. I love Hack for LA and will continue to work with them even though I got a new job!",true,false],["2022-04-24T22:01:53.988Z","jeanette.renema@gmail.com","Jeanette Renema","https://www.linkedin.com/in/jeanetterenema/","Yes","","Yes","Design Systems","UX Researcher & Lead UX Researcher","","2021-10-01T07:00:00.000Z","I got a new job, I produced something for my portfolio, I learned how to work better on a team, I worked on an enterprise project, I built a UX network ","Hack for LA gave me valuable experience working in product and design. The organization provided me with a wonderful team and I learned how to transfer my academic skills to the world of UX Research. ",true,false],["2022-05-29T19:26:57.990Z","cacho.matthew@gmail.com","Matthew Cacho","https://www.linkedin.com/in/matthew-a-cacho/","Yes","https://github.com/macho-catt","Yes","HackforLA Website, Lucky Parking","","Full Stack Developer, Technical Lead","2021-06-24T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I worked on an enterprise project, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","I joined talented teams where I learned how to collaborate with people, led and mentored developers, and gained experience as an engineer. Hack for LA is a great opportunity for people trying to hone their skills and grow their careers.",true,false],["2022-08-22T00:44:38.215Z","johnjbarrett22@gmail.com","John Barrett","https://www.linkedin.com/in/barrettjj/","Yes","https://github.com/JohnJBarrett22link","Yes","HackforLA Website","Development","Fullstack Developer","2018-12-03T08:00:00.000Z","I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I set up 2FA, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","Have been a part of many different teams over the past few years, though recently try to pick back up and be more aggressive. Part of Jobs for Hope, TDM Calc and now the website team as I am get back on track.",true,false],["2022-08-23T23:49:40.502Z","mukherjeeshruti88@gmail.com","Shruti Mukherjee ","https://www.linkedin.com/in/shruti-mukherjee-","Yes","","","HackforLA Website","UI/UX","UX Researcher ","2021-11-29T08:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team","My time at Hack for L.A. helped me learn how to work in a team, learn new tools and the language to pivot from academia into the industry. It helped me land a contract position at a research agency, and eventually helped me get my current full time position at Canada Life. The experience at Hack for L.A. was very valuable as I got to work with amazing people. ",true,false],["2023-08-28T00:40:59.045Z","babyyodanemo2020@gmail.com","Saumil Dhankar","https://www.linkedin.com/in/saumildhankar/","Yes","https://github.com/SAUMILDHANKAR","No","HackforLA Website","Development","Developer, merge team member, tech lead","2021-08-11T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I learned a new language, I worked on an enterprise project, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","I learned software engineering best practices from experienced professionals. I also worked on challenging development issues in a team environment using myriad of technologies. I got an opportunity to lead the dev team and help new developers make progress in their dev journey.",true,false]] - +[["2020-08-16T04:55:40.174Z","paridox@hotmail.com","Dean Church","https://www.linkedin.com/in/deanchurch/","Yes","","No","VRMS","Business Analyst","Product Roadmap construction","2019-07-01T07:00:00.000Z","I worked on an enterprise project, I worked on a project that will help the people of Los Angeles","I took the skills I have learned from HackforLA projects and applied them at work to orchestrate the launch of an MVP to help with Wildfire Mitigation throughout Southern California",true,false],["2020-08-16T05:28:29.558Z","paridox@hotmail.com","Dean Church","https://www.linkedin.com/in/deanchurch/","Yes","","No","VRMS","Business Analyst","","2019-07-01T07:00:00.000Z","I got a new job","As an over 50 year old career changer I was amazed at how supportive the community at HackforLA was in my finding meaningful employment in the local tech industry. Through exposure and application of Agile frameworks and user centered design thinking my time and practice at HfLA was instrumental in building my modern application skills competency and confidence. A direct result of my time at HfLA is that I was able to ace my 45min White Boarding interview where I had to diagram a workflow from end to end and identify areas that would benefit from automation. ",true,false],["2020-09-02T23:56:13.840Z","jpbubar@gmail.com","Josh Bubar","https://www.linkedin.com/in/joshua-bubar-25331a118/","Yes","https://github.com/jbubar","Yes","HackforLA Website","Development","Frontend Web Development","","I produced something for my portfolio, I increased the number of commits on my Github profile","I built my first page for hack for la! and it is this one!!! ...the wins page",true,false],["2020-11-30T03:47:02.249Z","alexandrastubbs12@gmail.com","Alex Stubbs","http://linkedin.com/in/alexandrajstubbs","Yes","","No","HackforLA Website","PM","","2020-06-01T07:00:00.000Z","I got a new job","I got a job as a product manager! This is something I have been working towards for awhile and Hack for LA helped me build the skills to achieve it. ",true,false],["2020-11-30T06:17:25.226Z","johnsritchey@yahoo.com","John R","https://www.linkedin.com/in/johnsritchey/","Yes","","No","311 Data","PM","","2019-09-17T07:00:00.000Z","I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team, I taught or mentored a person on another team, My team delivered software to a stakeholder, My team launched our MVP","Hack for LA has given me the opportunity to make connections with the people of Los Angeles tech community and local government that I would not have otherwise made. It is a joy to build things that actually help our community with people that are all focused on solving critical community challenges.",true,false],["2020-11-30T20:16:27.451Z","itsevalieu@gmail.com","Eva Lieu","https://www.linkedin.com/in/eva-lieu/","Yes","","","Shared Housing","Development","","","I got a new job, I improved my LinkedIn, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles","I joined the Shared Housing project and made a lot of friends with great people who helped me improve my coding skills. I learned how to work better on a team and eventually got a new job through one of my newly found friends here at HackforLA. I also enjoyed working on a project that was meant to help the people of LA, and it motivated me to keep learning front end development skills. ",true,true],["2020-11-30T20:55:42.121Z","prashantsingh071993@gmail.com","Prashant Singh","https://www.linkedin.com/in/prashant07singh/","Yes","","","100Automations, Food Oasis, TDM Calculator","Operations","","2020-10-01T07:00:00.000Z","I got a new job, I improved my LinkedIn, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles","I am grateful to the Hackforla team to give me an opportunity to contribute to their work and do what I like to do the best",true,false],["2020-12-01T17:00:51.013Z","sam@greenhacks.org","Sam Miyamoto","https://www.linkedin.com/in/e-samantha-miyamoto/","Yes","https://github.com/greenhacks","No","311 Data, HelloGov","QA, UI/UX, Accessibility testing","","2019-06-19T07:00:00.000Z","I improved my LinkedIn, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, Found a mentor and became part of a caring tech community!","HfLA makes me feel like I'm a part of the community, and though I might not be as active as I'd like, this group provides immense comfort! I'm glad to be part of the team here.",true,true],["2020-12-01T17:14:19.883Z","jenny@foodoasis.la","Jenny Mikesell","https://www.linkedin.com/in/jenny-mikesell","Yes","","","Food Oasis","Operations, UI/UX","","2018-08-01T07:00:00.000Z","I worked on a project that will help the people of Los Angeles","Food Oasis has an average of 400 unique visitors a day. Our database in Los Angeles has over 1000 listings. Since April 2020, community volunteers have helped us verify over 750 listings. We have proven that 30% of pantries have closed. The Department of Public Health just asked for a copy of our database to share with their nutritionists. We created an API and forked foodoasis.net to included Northern California, Oregon, and Hawaii. ",true,false],["2020-12-04T00:20:00.683Z","jake.mensch@gmail.com","Jake Mensch","https://www.linkedin.com/in/jacob-mensch/","Yes","https://github.com/jmensch1","Yes","311 Data","Development","","2020-02-15T08:00:00.000Z","I learned how to work better on a team, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, My team launched our MVP","I met some great people and built some cool apps.",true,false],["2020-12-17T22:07:08.182Z","joshuazrobins@gmail.com","Josh Robins","https://www.linkedin.com/in/joshuazrobins","Yes","","No","Food Oasis, HackforLA Website, Railstats LA, Work for LA","Business Analyst, Content, Data, Development, PM, QA, UI/UX","","2016-05-10T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I learned a new language, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, My team delivered software to a stakeholder, My team launched our MVP, I joined the leadership team in 2017 and got the opportunity to invest back into the Hack for LA community by organizing teams, projects, and events","I came to Hack for LA in 2016 as a full-stack web developer and was part of the founding group of Food Oasis LA. I originally joined this community because I wanted to make the transition to Product Management and gain experience building projects for real-world needs. Eventually, I joined the leadership team and ran our Downtown LA hack nights from 2017 to 2019 before stepping back to focus on personal endeavors. ",true,false],["2020-12-21T19:41:43.053Z","tmalstead@codeforamerica.org","Timothy Malstead","https://www.linkedin.com/in/timmalstead/","Yes","https://github.com/timmalstead-cfa","Yes","Food Oasis, Home Unite Us, Not Today","Development","","2019-12-21T08:00:00.000Z","I got a new job","I have begun a community fellowship with Code for America! We will be working on ways to allow justice impacted people easier access to public resources.",true,false],["2020-12-24T03:23:37.075Z","j100892@gmail.com","Daniel Lee","https://www.linkedin.com/in/kipsbaydan/","Yes","","","Record Clearance Project","PM","","2020-09-28T07:00:00.000Z","I got a new job, My team launched our MVP","Hack for LA is where I really had my first hands-on exposure to civic technology. Bonnie Wolfe and Dean Church really helped me bring the record clearance project off the ground and we currently have a tech lead and a development team building designs that our design/research team worked on. I also got an offer for my first civic tech design position today and am grateful for Hack for LA playing an integral part of it. Shoutout to the Record Clearance team and for all the hard work over the past few months! ",true,false],["2021-04-06T16:13:30.983Z","codewilling@gmail.com","Sean Flores","http://www.linkedin.com/in/sean-flores","Yes","","","Civic Tech Index","Development","","2020-09-01T07:00:00.000Z","I got a new job, I learned how to work better on a team, I increased the number of commits on my Github profile, I learned a new language, I worked on a project that will help the people of Los Angeles, I found multiple mentors","I could never commit to contributing to open source. The fear of not knowing enough kept me from applying my skills and full of imposter syndrome, until I began volunteering for Hack for LA. In addition to being able to help my community, I also gained access to a treasure-trove of resources through my colleagues, and found mentors that would've been inaccessible otherwise. I can only describe my experience with Hack for LA as feeling very lucky and look forward to continuing to contributing in the future.",true,false],["2021-05-10T23:57:41.849Z","gothe.s@northeastern.edu","Sharwari Gothe","https://www.linkedin.com/in/sharwarigothe/","Yes","","","311 Data","Development","","2021-02-04T08:00:00.000Z","I got a new job","I got a job at TCS as a Software Developer.",true,false],["2021-05-30T17:32:19.549Z","avali4907@outlook.com","Ava Li","","","","","HackforLA Website","Development","","2021-04-21T07:00:00.000Z","I learned how to work better on a team","I created documentation for the HackForLA Website project and everyone on the team loved it! It feels very nice to receive affirmations of appreciation.",true,false],["2021-06-11T21:13:46.096Z","thomisfrank@gmail.com","Thomas Phillip Franklin II","https://www.linkedIn.com/in/thomisfrank","Yes","","","311 Data","UI/UX","","2020-04-01T07:00:00.000Z","I got a new job, I worked on a project that will help the people of Los Angeles","I joined hack4LA in April of 2020 right after graduating General Assembly it was my first design role outside of the boot camp. I was able to work on the 311 data project which is improving the lives of Angelinos. \n\nUsing that foundation I was able to get a few freelance positions and eventually transition to being in the first cohort of Amazon's User Experience Research and Design Apprenticeship. ",true,true],["2021-06-18T21:00:10.288Z","pvonhagen26@gmail.com","Paul von Hagen","https://www.linkedin.com/in/paulvonhagen26/","Yes","https://github.com/paulsvh","Yes","HackforLA Website","Development","","2021-03-15T07:00:00.000Z","I got a new job","Hack For LA gave me a great foundation in working with others in a shared codebase. Not only did my experience here help lead me to a new job, I truly enjoyed all of my interactions with everyone on the team. Special shout out to Josh Bubar for being so welcoming and always happy to help others.",true,true],["2021-07-02T19:34:18.130Z","atkendis@gmail.com","Adam Kendis","https://www.linkedin.com/in/adamkendis","No","https://github.com/adamkendis","Yes","311 Data","Development","","2020-01-01T08:00:00.000Z","I got a new job, I produced something for my portfolio, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles, My team launched our MVP","Hack for LA gave me valuable experience working with product, UI/UX, and data teams. I met some awesome people, learned a lot, and got a new job!",true,false],["2021-07-10T22:46:42.566Z","niven.prasad@gmail.com","Niven Prasad","https://www.linkedin.com/in/nivenprasad/","Yes","https://github.com/NivenPrasad","Yes","100Automations","PM","","2020-06-01T07:00:00.000Z","I got a new job","I recently joined joined Homebot as a full-time Technical Product Manager! I'm working with APIs, integrations, and automations - so grateful for all my experience at Hack for LA and for all the people I got to work with both in the 100 Automations project and across other projects (and still do occasionally). Feel free to reach out if you ever want to connect or share experiences!",true,false],["2021-07-28T17:15:35.150Z","experimentsinhonesty@gmail.com","Bonnie Wolfe","https://linkedin/in/BonnieAWolfe","Yes","https://github.com/experimentsinhonesty","Yes","100Automations, 311 Data, Civic Opportunity Project, Civic Tech Index, Engage, Food Oasis, HackforLA Website, Home Unite Us, Record Clearance Project, TDM Calculator, VRMS","Operations, PM, QA","","2018-10-28T07:00:00.000Z","I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I set up 2FA, I worked on an enterprise project, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team, I taught or mentored a person on another team, My team delivered software to a stakeholder, My team launched our MVP","I learned how to create an inclusive community and working environments where the there are not artificial boundaries to personal growth",true,false],["2021-08-20T06:42:45.341Z","jpbubar@gmail.com","Josh Bubar","https://www.linkedin.com/in/jbubar/","Yes","https://github.com/jbubar","Yes","HackforLA Website, VRMS","Development","","2019-09-19T07:00:00.000Z","I got a new job, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I taught or mentored a person on my team","I got my first JOB in tech!! I learned so much from contributing to Hack for LA and I will use all of it in my new job!",true,true],["2021-09-03T02:17:49.434Z","evanjyang4@gmail.com","Evan Yang","https://www.linkedin.com/in/evanjyang/","Yes","www.github.com/evanyang1","Yes","VRMS","Development","","2021-08-07T07:00:00.000Z","I got a new job","Got a contract software engineering job (through a 3rd party company) at Facebook! I'm excited, but the journey has just started, got a long way to go!",true,false],["2021-11-01T22:29:30.304Z","janieche1@gmail.com","Janie Chen","https://www.linkedin.com/in/janiechen09","Yes","","No","HackforLA Website","UI/UX","","2021-07-01T07:00:00.000Z","I got a new job","I landed my first full-time role as a Product Designer @ DocuSign! Working with the HfLA team helped build up my confidence as a designer in a structured and supportive environment. It’s a great opportunity to put what I’ve learned into practice and improve both my design and collaboration skills. ",true,true],["2021-11-05T18:42:20.543Z","senbasudhara@gmail.com","Basudhara Sen","https://www.linkedin.com/in/basudhara-sen-ph-d-718b042b/","Yes","https://github.com/Basu3040","No","HackforLA Website","UI/UX","UX Research Lead","2021-07-29T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I learned a new language","HfLA gave me a 360-degree view of the UX processes. I was transitioning from academia to UX and I got hands-on experience working with diverse stakeholders in an agile environment. I worked with great team members who were always willing to collaborate and on task. I am thankful to HfLA for this awesome opportunity and I strode with confidence in UX job interviews. I landed a job as a UX Researcher at Symplr.",true,true],["2021-12-07T00:56:25.788Z","myechoproject@gmail.com","Eric Cho","https://www.linkedin.com/in/echoechoecho/","Yes","","Yes","311 Data","PM","Product Manager","2021-09-06T07:00:00.000Z","I was admitted into an MBA program.","I was applying for an MBA program to help pivot my career into Product Management. The time I spent learning new skills and working with like-minded individuals played a significant role in building my applicant profile. ",true,true],["2022-01-07T04:13:50.643Z","chalimar@gmail.com","Chali Prasertsri Stoyanoff","https://www.linkedin.com/in/cprasertsri/","Yes","https://github.com/chalimar","Yes","Civic Tech Index, Youth Justice Nav","UI/UX","Lead UX Designer","2020-02-04T08:00:00.000Z","I got a new job, I produced something for my portfolio, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","My experience with Hack for LA helped me land a job offer for Lead Product Designer!\n\nIn joining HfLA, I was looking to work with cross-functional team members and launch products that empower users and communities. The overall experience has helped me improve my personal tenacity, confidence as a design leader, and ability to communicate effectively.\n\nHfLA has been an invaluable resource for me, and I am thankful for the colleagues, professional growth, and support I’ve gained along the way.",true,false],["2022-01-08T02:47:43.080Z","ahoang94@gmail.com","Anh Hoang","https://www.linkedin.com/in/anhhoang-design/","Yes","","","Design Systems, HackforLA Website","UI/UX","UX/UI Designer","2021-07-19T07:00:00.000Z","I got a new job, I learned how to work better on a team, I worked on two or more projects","Hack for LA was a great resume and experience booster as someone who had just graduated from a UX bootcamp but had minimal real-world experience in the field. Working on the HfLA website and Design Systems projects allowed me to collaborate with not only other designers but also researchers and developers, and I was fortunate enough to receive mentorship from PM Hana Stevenson, whose career advice was keen and invaluable. I can say with confidence that my work at HfLA, especially for the Design Systems team, helped me land my new role as Product Designer at Lumanu.",true,false],["2022-02-05T02:59:57.876Z","jonathan.ko523@gmail.com","Jonathan Ko","https://www.linkedin.com/in/jonathanko523/","Yes","https://github.com/Jonathanko52","No","TDM Calculator, VRMS","Development","Frontend","","I got a new job","Hack for LA allowed me to refine my ability to work with others, expand my knowledge regarding web development, and introduced me to peers and mentors who have been and continue to be invaluable resources to me. Thanks to this organization, I've found my first job as a software engineer!",true,false],["2022-02-16T03:18:44.711Z","swerdlowbenjamin@gmail.com","Ben Swerdlow","","","","","BallotNav, New Schools Today","Development, PM","","2019-04-30T07:00:00.000Z","I got into U Chicago!","I got into U Chicago!! The leadership skills that the Hack for LA team were integral to my acceptance!",true,false],["2022-03-11T20:01:02.689Z","tanzhouinfo@gmail.com","Tan Zhou","https://www.linkedin.com/in/tan-zhou/","Yes","https://github.com/tan-zhou","Yes","Brigade Organizer’s Playbook, Civic Opportunity Project","UI/UX","UX Researcher","2020-08-01T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I worked on two or more projects","My journey at Hack for LA got to be one of the most engaging and rewarding experience. I was able to improve in my area of interests working on projects that made a positive impact. I am proud to witness how the UX/UI community of practice has grown to connect and uplift people from such diverse backgrounds. Recommend it for anyone that's looking to get involved with the civic tech movement and improve their skills.",true,false],["2022-03-23T01:38:52.891Z","juliaa423@gmail.com","Julia Anderson","https://www.linkedin.com/in/julia-a-anderson/","Yes","","","Home Unite Us","UI/UX","","2020-08-01T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I worked on a project that will help the people of Los Angeles","Hack for LA taught me that design can't be done in a vacuum. Collaborating, designing and iterating together helped set the foundation for the rest of my design career. I felt that my strengths as a writer and designer were actualized through my supportive team. Not only did I learn what it takes to make a design system, but I discovered how satisfying it can be to use technology for good. ",true,false],["2022-04-10T20:24:50.437Z","sydney.walcoff@gmail.com","Sydney Walcoff","https://www.linkedin.com/in/sydneywalcoff/","Yes","https://github.com/sydneywalcoff","Yes","Expunge Assist, HackforLA Website","Development","Frontend Developer","2021-11-29T08:00:00.000Z","I got a new job, I improved my LinkedIn, I increased the number of commits on my Github profile, I worked on a project that will help the people of Los Angeles, I taught or mentored a person on my team","Hack for LA is a great way to get hands-on experience while also working on projects to improve the lives of Angelenos. I love Hack for LA and will continue to work with them even though I got a new job!",true,false],["2022-04-24T22:01:53.988Z","jeanette.renema@gmail.com","Jeanette Renema","https://www.linkedin.com/in/jeanetterenema/","Yes","","Yes","Design Systems","UX Researcher & Lead UX Researcher","","2021-10-01T07:00:00.000Z","I got a new job, I produced something for my portfolio, I learned how to work better on a team, I worked on an enterprise project, I built a UX network ","Hack for LA gave me valuable experience working in product and design. The organization provided me with a wonderful team and I learned how to transfer my academic skills to the world of UX Research. ",true,false],["2022-05-29T19:26:57.990Z","cacho.matthew@gmail.com","Matthew Cacho","https://www.linkedin.com/in/matthew-a-cacho/","Yes","https://github.com/macho-catt","Yes","HackforLA Website, Lucky Parking","","Full Stack Developer, Technical Lead","2021-06-24T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I worked on an enterprise project, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","I joined talented teams where I learned how to collaborate with people, led and mentored developers, and gained experience as an engineer. Hack for LA is a great opportunity for people trying to hone their skills and grow their careers.",true,false],["2022-08-22T00:44:38.215Z","johnjbarrett22@gmail.com","John Barrett","https://www.linkedin.com/in/barrettjj/","Yes","https://github.com/JohnJBarrett22link","Yes","HackforLA Website","Development","Fullstack Developer","2018-12-03T08:00:00.000Z","I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I set up 2FA, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","Have been a part of many different teams over the past few years, though recently try to pick back up and be more aggressive. Part of Jobs for Hope, TDM Calc and now the website team as I am get back on track.",true,false],["2022-08-23T23:49:40.502Z","mukherjeeshruti88@gmail.com","Shruti Mukherjee ","https://www.linkedin.com/in/shruti-mukherjee-","Yes","","","HackforLA Website","UI/UX","UX Researcher ","2021-11-29T08:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team","My time at Hack for L.A. helped me learn how to work in a team, learn new tools and the language to pivot from academia into the industry. It helped me land a contract position at a research agency, and eventually helped me get my current full time position at Canada Life. The experience at Hack for L.A. was very valuable as I got to work with amazing people. ",true,false],["2023-08-28T00:40:59.045Z","babyyodanemo2020@gmail.com","Saumil Dhankar","https://www.linkedin.com/in/saumildhankar/","Yes","https://github.com/SAUMILDHANKAR","No","HackforLA Website","Development","Developer, merge team member, tech lead","2021-08-11T07:00:00.000Z","I got a new job, I produced something for my portfolio, I improved my LinkedIn, I learned how to work better on a team, I increased the number of commits on my Github profile, I learned a new language, I worked on an enterprise project, I worked on a project that will help the people of Los Angeles, I worked on two or more projects, I taught or mentored a person on my team","I learned software engineering best practices from experienced professionals. I also worked on challenging development issues in a team environment using myriad of technologies. I got an opportunity to lead the dev team and help new developers make progress in their dev journey.",true,false]] \ No newline at end of file diff --git a/_data/internal/communities/data-science.yml b/_data/internal/communities/data-science.yml index ea93999702..cb8398c18d 100644 --- a/_data/internal/communities/data-science.yml +++ b/_data/internal/communities/data-science.yml @@ -11,8 +11,6 @@ alt: 'A person uses a laptop to review a data dashboard' icon: /assets/images/hero/communities-icons/data-science.png -meeting-times: Mondays 7:00-8:00 pm PT - leadership-type: Mentor Led leadership: - name: Sophia Alice @@ -32,7 +30,7 @@ leadership: links: - name: Slack url: https://app.slack.com/client/T04502KQX/CGRATJCCF - - name: Github + - name: GitHub url: https://github.com/hackforla/data-science/ recruiting-message: diff --git a/_data/internal/communities/engineering.yml b/_data/internal/communities/engineering.yml index c833570e7c..b5a5599256 100644 --- a/_data/internal/communities/engineering.yml +++ b/_data/internal/communities/engineering.yml @@ -11,9 +11,7 @@ alt: 'A computer screen shows a diagram used to manage code development' icon: /assets/images/hero/communities-icons/engineering.png -meeting-times: Thursdays 6:00-7:00 pm PT - -leadership-type: Peer Led +leadership-type: Community Led leadership: - name: Micah Elm role: Co-lead @@ -43,7 +41,7 @@ leadership: links: - name: Slack url: https://app.slack.com/client/T04502KQX/C01CU709SER - - name: Github + - name: GitHub url: https://github.com/hackforla/engineering recruiting-message: diff --git a/_data/internal/communities/operations.yml b/_data/internal/communities/operations.yml index d29d246930..6129c760ab 100644 --- a/_data/internal/communities/operations.yml +++ b/_data/internal/communities/operations.yml @@ -11,23 +11,38 @@ alt: 'A dramatic closeup of a screen filled with code' icon: /assets/images/hero/communities-icons/operations.png -meeting-times: Wednesdays 6:00-7:00 pm PT - leadership-type: Community Led leadership: - name: Chelsey Beck + github-handle: chelseybeck role: Co-lead links: slack: https://hackforla.slack.com/team/U01J93AQKSS github: https://github.com/chelseybeck picture: https://avatars.githubusercontent.com/chelseybeck - - name: Ernie Pelayo + - name: Alex English + github-handle: ale210 + role: Co-lead + links: + slack: https://hackforla.slack.com/team/U078B1S0XDM + github: https://github.com/ale210 + picture: https://avatars.githubusercontent.com/ale210 + - name: Ryan Sakuma + github-handle: RSkuma role: Co-lead links: - slack: https://hackforla.slack.com/team/U046MDSM3PA - github: https://github.com/erniep278 - picture: https://avatars.githubusercontent.com/erniep278 + slack: https://hackforla.slack.com/team/U078U294XB6 + github: https://github.com/RSkuma + picture: https://avatars.githubusercontent.com/RSkuma + - name: Sudha Raamakrishnan + github-handle: sudhara + role: Ops PM + links: + slack: https://hackforla.slack.com/team/U07FJRNN9MK + github: https://github.com/sudhara + picture: https://avatars.githubusercontent.com/sudhara - name: Dean Church + github-handle: Rankazze role: Co-lead links: slack: https://hackforla.slack.com/team/UJR0UKBN1 @@ -37,7 +52,7 @@ leadership: links: - name: Slack url: https://app.slack.com/client/T04502KQX/CV7QGL66B - - name: Github + - name: GitHub url: https://github.com/hackforla/ops recruiting-message: diff --git a/_data/internal/communities/product-management.yml b/_data/internal/communities/product-management.yml index 64c8097378..d77998d127 100644 --- a/_data/internal/communities/product-management.yml +++ b/_data/internal/communities/product-management.yml @@ -11,8 +11,6 @@ alt: 'Several people around a small table listen intently as one person speaks.' icon: /assets/images/hero/communities-icons/product-management.png -meeting-times: Fridays 12:00-1:00 pm PT - leadership-type: Mentor Led leadership: - name: Bonnie Wolfe @@ -25,7 +23,7 @@ leadership: links: - name: Slack url: https://app.slack.com/client/T04502KQX/C010LNXH2JY/details/ - - name: Github + - name: GitHub url: https://github.com/hackforla/product-management recruiting-message: diff --git a/_data/internal/communities/ui-ux.yml b/_data/internal/communities/ui-ux.yml index 8c52ce3427..1d144f77ba 100644 --- a/_data/internal/communities/ui-ux.yml +++ b/_data/internal/communities/ui-ux.yml @@ -11,9 +11,7 @@ alt: 'A board full of Post-it notes is used as a communication tool' icon: /assets/images/hero/communities-icons/ui-ux.png -meeting-times: Wednesdays 6:00-7:00 PM PT - -leadership-type: Peer Led +leadership-type: Community Led leadership: - name: Aparna Gopal role: Co-lead @@ -48,7 +46,7 @@ leadership: links: - name: Slack url: https://app.slack.com/client/T04502KQX/C017ESHSMNG/ - - name: Github + - name: GitHub url: https://github.com/hackforla/UI-UX recruiting-message: diff --git a/_data/internal/former-sponsors-partners.yml b/_data/internal/former-sponsors-partners.yml new file mode 100644 index 0000000000..98b2d56add --- /dev/null +++ b/_data/internal/former-sponsors-partners.yml @@ -0,0 +1,3 @@ +- name: Code for America + image: /assets/images/former-sponsors-partners/code-for-america.svg + link: https://www.codeforamerica.org/ \ No newline at end of file diff --git a/_data/internal/partners.yml b/_data/internal/partners.yml index 607e2f8537..113590295e 100644 --- a/_data/internal/partners.yml +++ b/_data/internal/partners.yml @@ -3,6 +3,11 @@ link: https://empowerla.org/ program-area: - Citizen Engagement +- name: Atwater Village + image: /assets/images/partners/atwater-village.png + link: https://www.atwatervillage.org/ + program-area: + - Citizen Engagement - name: Yale Open Lab image: /assets/images/partners/yale-open-labs.svg link: https://openlab.yale.edu/ diff --git a/_data/internal/privacy-policy.yml b/_data/internal/privacy-policy.yml index c39e21e2d6..1cb9eb0bd2 100644 --- a/_data/internal/privacy-policy.yml +++ b/_data/internal/privacy-policy.yml @@ -67,7 +67,7 @@ privacy-policy: | We do not knowingly collect, maintain, or use personal information from children under 13 years of age, and no part of our Site is directed to children. - If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at [privacy@hackforla.org](privacy@hackforla.org) and reference “Child Privacy Report” in the subject line. + If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at [privacy@hackforla.org](mailto: privacy@hackforla.org) and reference “Child Privacy Report” in the subject line. ## Security @@ -77,7 +77,7 @@ privacy-policy: | ## Right to be forgotten and rectification - You may request that we make corrections to any personal data that is stored on our internal databases at any time. You may request that incomplete data be completed or that incorrect data be corrected. Requests can be submitted to [privacy@hackforla.org](privacy@hackforla.org) and reference “Hack for LA Public Website” in the subject line. + You may request that we make corrections to any personal data that is stored on our internal databases at any time. You may request that incomplete data be completed or that incorrect data be corrected. Requests can be submitted to [privacy@hackforla.org](mailto: privacy@hackforla.org) and reference “Hack for LA Public Website” in the subject line. ## Changes @@ -89,7 +89,7 @@ privacy-policy: | ## Questions - If you have any questions, comments, concerns, or complaints related to our websites, please contact us by email at [privacy@hackforla.org](privacy@hackforla.org), or by mail at: + If you have any questions, comments, concerns, or complaints related to our websites, please contact us by email at [privacy@hackforla.org](mailto: privacy@hackforla.org), or by mail at: Civic Tech Structure, Inc.\ Ref: Hack for LA, HackforLA.org\ diff --git a/_data/internal/toolkitresources.yml b/_data/internal/toolkitresources.yml index 8f5870a185..9c8822c3fa 100644 --- a/_data/internal/toolkitresources.yml +++ b/_data/internal/toolkitresources.yml @@ -19,7 +19,7 @@ - GitHub contributors: recommended-by: Bonnie Wolfe - svg: svg/icon-github-small.svg + svg: svg/icon-github.svg resource-url: 'https://github.com/' - title: Zoom diff --git a/_guide-pages/2FA.html b/_guide-pages/2FA.html index 134976ccbc..2430dff7c2 100644 --- a/_guide-pages/2FA.html +++ b/_guide-pages/2FA.html @@ -42,7 +42,7 @@
Visit and follow

Frequently Asked Questions

diff --git a/_includes/about-page/about-card-news.html b/_includes/about-page/about-card-news.html index 04b08b0539..76d81e9256 100644 --- a/_includes/about-page/about-card-news.html +++ b/_includes/about-page/about-card-news.html @@ -11,12 +11,12 @@
{% endfor %} - {% for testemonial in site.data.internal.testimonials %} + {% for testimonial in site.data.internal.testimonials %}
-

{{testemonial.quote}}

+

{{testimonial.quote}}

- — {{testemonial.source}} - {{testemonial.source}} + — {{testimonial.source}} + {{testimonial.source}}
{% endfor %} diff --git a/_includes/calendar.html b/_includes/calendar.html deleted file mode 100644 index 24bfc3f616..0000000000 --- a/_includes/calendar.html +++ /dev/null @@ -1,10 +0,0 @@ -
-
-

More Upcoming Events

-
-
- -
-
-
-
\ No newline at end of file diff --git a/_includes/current-guides.html b/_includes/current-guides.html index b03a7dfe91..0cbc176ff7 100644 --- a/_includes/current-guides.html +++ b/_includes/current-guides.html @@ -74,10 +74,10 @@

External Resources

{%- endif -%}
-

{{ item.title }}

+

{{ item.title }}

{{ item.description }}

- + {% include svg/outer-link.svg %} diff --git a/_includes/events-page/header-container-content.html b/_includes/events-page/header-container-content.html index 2476fd85f3..ee9ee9f253 100644 --- a/_includes/events-page/header-container-content.html +++ b/_includes/events-page/header-container-content.html @@ -2,30 +2,48 @@

Events

-

+

Hack for LA was incubated in the Code for America Brigade Network and continues the valuable work under Civic Tech Structure, Inc. a network of civic-minded technologists who contribute their skills toward using the web as a platform for local government and community service. -

+

- +

To learn more, watch the - Ted Talk - by Code for America founder, Jennifer Pahlka, on maintaining a better government through code. + Ted Talk + by Code for America founder, Jennifer Pahlka, on maintaining a better + government through code.

- + + + + +
diff --git a/_includes/events-page/right-col-content-check.html b/_includes/events-page/right-col-content-check.html new file mode 100644 index 0000000000..e122fb7d6b --- /dev/null +++ b/_includes/events-page/right-col-content-check.html @@ -0,0 +1,32 @@ +

+ + Online Project Team Meetings +

+
+
+
+ +
+
+

+ Please review the listing of project team meeting times to find a + project that fits your schedule. You are welcome to attend a project + team meeting after you have completed + Onboarding. +

+
+
+
+
+ {% assign days-of-week = + "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday" | split: "," %} + {% for day in days-of-week %} +
+

{{day}}

+
    +
    + {% endfor %} +
    +
    + + diff --git a/_includes/events-page/right-col-content.html b/_includes/events-page/right-col-content.html index 88507c09e6..eadd73df18 100644 --- a/_includes/events-page/right-col-content.html +++ b/_includes/events-page/right-col-content.html @@ -5,15 +5,10 @@

    - +
    -

    - Please review the listing of project team meeting times to find a - project that fits your schedule. You are welcome to attend a project - team meeting after you have completed - Onboarding. -

    +

    We have teams that meet at various times. You are welcome to attend a project team meeting after you have completed Onboarding, and if the team currently has an open role. You can find open roles at the end of the Onboarding.

    @@ -27,6 +22,7 @@

    {{day}}

    {% endfor %}
    +

    *This meeting is not weekly, check project link for more details.

    diff --git a/_includes/resource-card.html b/_includes/resource-card.html index 0070801608..d0c0624dc3 100644 --- a/_includes/resource-card.html +++ b/_includes/resource-card.html @@ -2,14 +2,16 @@ {% assign image = include.image %} {% assign name = include.name %} {% assign lowercaseName = include.name | downcase %} +{% assign hyphenatedName = lowercaseName | replace: ' ', '-' %} - - +
  • {% if lowercaseName == 'github' %} -

    +

    GitHub

    {% else %} -

    +

    {{ name }}

    {% endif %} diff --git a/_includes/svg/icon-github-color.svg b/_includes/svg/icon-github-color.svg deleted file mode 100644 index b028f0eddc..0000000000 --- a/_includes/svg/icon-github-color.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/_includes/svg/icon-github-small.svg b/_includes/svg/icon-github-small.svg deleted file mode 100644 index 8571299bd1..0000000000 --- a/_includes/svg/icon-github-small.svg +++ /dev/null @@ -1,71 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/_includes/svg/icon-slack-color.svg b/_includes/svg/icon-slack-color.svg deleted file mode 100644 index 979329271f..0000000000 --- a/_includes/svg/icon-slack-color.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_layouts/default-markdown.html b/_layouts/default-markdown.html index 56f11ce4fb..db2d682d36 100644 --- a/_layouts/default-markdown.html +++ b/_layouts/default-markdown.html @@ -15,7 +15,6 @@ -
    \ No newline at end of file diff --git a/_layouts/default.html b/_layouts/default.html index 239a05ddcc..782c9f19b2 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -15,7 +15,6 @@ - diff --git a/_data/internal/program-areas/citizen-engagement-card.yml b/_program-areas/citizen-engagement-card.yml similarity index 100% rename from _data/internal/program-areas/citizen-engagement-card.yml rename to _program-areas/citizen-engagement-card.yml diff --git a/_data/internal/program-areas/civic-tech-infrastructure-card.yml b/_program-areas/civic-tech-infrastructure-card.yml similarity index 100% rename from _data/internal/program-areas/civic-tech-infrastructure-card.yml rename to _program-areas/civic-tech-infrastructure-card.yml diff --git a/_data/internal/program-areas/diversity-equity-inclusion-card.yml b/_program-areas/diversity-equity-inclusion-card.yml similarity index 100% rename from _data/internal/program-areas/diversity-equity-inclusion-card.yml rename to _program-areas/diversity-equity-inclusion-card.yml diff --git a/_data/internal/program-areas/environment-card.yml b/_program-areas/environment-card.yml similarity index 100% rename from _data/internal/program-areas/environment-card.yml rename to _program-areas/environment-card.yml diff --git a/_data/internal/program-areas/justice-card.yml b/_program-areas/justice-card.yml similarity index 100% rename from _data/internal/program-areas/justice-card.yml rename to _program-areas/justice-card.yml diff --git a/_data/internal/program-areas/social-safety-net-card.yml b/_program-areas/social-safety-net-card.yml similarity index 100% rename from _data/internal/program-areas/social-safety-net-card.yml rename to _program-areas/social-safety-net-card.yml diff --git a/_data/internal/program-areas/vote-representation-card.yml b/_program-areas/vote-representation-card.yml similarity index 100% rename from _data/internal/program-areas/vote-representation-card.yml rename to _program-areas/vote-representation-card.yml diff --git a/_data/internal/program-areas/workforce-development-card.yml b/_program-areas/workforce-development-card.yml similarity index 100% rename from _data/internal/program-areas/workforce-development-card.yml rename to _program-areas/workforce-development-card.yml diff --git a/_projects/100-automations.md b/_projects/100-automations.md index b07dc71dec..c087c48c90 100644 --- a/_projects/100-automations.md +++ b/_projects/100-automations.md @@ -28,6 +28,7 @@ leadership: github: 'https://github.com/Olivia-Chiong' picture: 'https://avatars.githubusercontent.com/Olivia-Chiong' - name: Muhi-Dean Othman + github-handle: role: Full-Stack Developer links: slack: 'https://hackforla.slack.com/team/U01F5K8DDPW' diff --git a/_projects/311-data.md b/_projects/311-data.md index dcc18d48b9..c438dbafba 100644 --- a/_projects/311-data.md +++ b/_projects/311-data.md @@ -34,13 +34,6 @@ leadership: slack: https://hackforla.slack.com/team/U05JKGV3F4N github: https://github.com/annaseulgi picture: https://avatars.githubusercontent.com/annaseulgi - - name: Ahmed Awadalla - github-handle: ahmedsalah0130 - role: Product Manager - links: - slack: https://hackforla.slack.com/team/U05Q80JEGG4 - github: https://github.com/ahmedsalah0130 - picture: https://avatars.githubusercontent.com/ahmedsalah0130 - name: Bethlehem Berhane github-handle: bberhane role: Product Manager @@ -62,6 +55,20 @@ leadership: slack: https://hackforla.slack.com/team/U03SUUZMFEV github: https://github.com/edwinjue picture: https://avatars.githubusercontent.com/edwinjue + - name: Allison Jeon + github-handle: allisonjeon + role: UX Design Lead + links: + slack: https://hackforla.slack.com/team/U05JP94R9B7 + github: https://github.com/allisonjeon + picture: https://avatars.githubusercontent.com/allisonjeon + - name: Joy Truex + github-handle: Joy-Truex + role: UX Design Lead + links: + slack: https://hackforla.slack.com/team/U03VBPSEH52 + github: https://github.com/Joy-Truex + picture: https://avatars.githubusercontent.com/Joy-Truex links: - name: GitHub url: 'https://github.com/hackforla/311-data' diff --git a/_projects/ballot-nav.md b/_projects/ballot-nav.md index 693953c764..1833ba9229 100644 --- a/_projects/ballot-nav.md +++ b/_projects/ballot-nav.md @@ -7,30 +7,35 @@ alt: "Ballot Nav" image-hero: /assets/images/projects/ballot-nav-hero.png leadership: - name: Karen Coronel + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U010KUGJATC' github: 'https://github.com/kcoronel' picture: 'https://avatars.githubusercontent.com/kcoronel' - name: Stacey Rebekah Scott + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U02U9Q5DUF6' github: 'https://github.com/staceyrebekahscott' picture: 'https://avatars.githubusercontent.com/staceyrebekahscott' - name: Layne Mostyn + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U032H8FJX6U' github: 'https://github.com/layneam' picture: 'https://avatars.githubusercontent.com/layneam' - name: Andrew Steman + github-handle: role: Lead Developer links: slack: 'https://hackforla.slack.com/team/U01AP5R8U6P' github: 'https://github.com/aNullValue' picture: 'https://avatars.githubusercontent.com/aNullValue' - name: Zuri Smith + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U035UP9N5PG' diff --git a/_projects/brigade-organizers-playbook.md b/_projects/brigade-organizers-playbook.md index 6a1bdeec19..3f60c5ef9c 100644 --- a/_projects/brigade-organizers-playbook.md +++ b/_projects/brigade-organizers-playbook.md @@ -9,30 +9,35 @@ program-area: - Civic Tech Infrastructure leadership: - name: Bonnie Wolfe + github-handle: role: BOP Project Lead links: slack: 'https://hackforla.slack.com/archives/C01Q24YF56J' github: 'https://github.com/experimentsinhonesty' picture: https://avatars.githubusercontent.com/experimentsinhonesty - name: Aleiya Gafar + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U01K7QMQ4TC' github: 'https://github.com/ag2463' picture: https://avatars.githubusercontent.com/ag2463 - name: Evan Stalker + github-handle: role: Lead Designer links: slack: 'https://hackforla.slack.com/team/U04M979AY3G' github: 'https://github.com/ejstalker' picture: https://avatars.githubusercontent.com/ejstalker - name: Liz Brown + github-handle: role: UX Designer links: slack: 'https://hackforla.slack.com/team/U052DR4HVJS' github: 'https://github.com/ermbrown' picture: https://avatars.githubusercontent.com/ermbrown - - name: Katrina Bonoan + - name: Katrina Bonoan + github-handle: role: UX Designer links: slack: 'https://hackforla.slack.com/team/U052LER0010' diff --git a/_projects/civic-opportunity-project.md b/_projects/civic-opportunity-project.md index 9bcf580f04..f49e489e06 100644 --- a/_projects/civic-opportunity-project.md +++ b/_projects/civic-opportunity-project.md @@ -7,6 +7,7 @@ alt: 'Civic Opportunity Project' image-hero: /assets/images/projects/civic-opportunity-project-hero.png leadership: - name: Ray Fambro + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U015QPJS34M' diff --git a/_projects/civic-tech-index.md b/_projects/civic-tech-index.md index ccb914cc8c..79992af3b7 100644 --- a/_projects/civic-tech-index.md +++ b/_projects/civic-tech-index.md @@ -10,96 +10,112 @@ alt: "Civic Tech Index" image-hero: /assets/images/projects/civic-tech-index-hero.png leadership: - name: Bonnie Wolfe + github-handle: role: Agile Coach and Stakeholder Rep links: slack: 'https://hackforla.slack.com/team/UE1UG1YFP' github: 'https://github.com/ExperimentsInHonesty' picture: https://avatars.githubusercontent.com/ExperimentsInHonesty - name: Cynthia Kiser + github-handle: role: Architectural Advisor links: slack: 'https://hackforla.slack.com/team/U04MFPQDN' github: 'https://github.com/cnk' picture: https://avatars.githubusercontent.com/cnk - name: Kevin Phan + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U02B90U9FPS' github: 'https://github.com/kevindphan' picture: https://avatars.githubusercontent.com/kevindphan - name: Sean Sada + github-handle: role: Product Manager links: slack: https://hackforla.slack.com/team/U016XE06ZS5 github: https://github.com/smsada picture: https://avatars.githubusercontent.com/smsada - name: Briana Bennett + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U031BRKV59C' github: 'https://github.com/bribenn' picture: https://avatars.githubusercontent.com/bribenn - name: Chali Prasertsri + github-handle: role: UX Lead links: slack: 'https://hackforla.slack.com/team/USLBE6X4M' github: 'https://github.com/chalimar' picture: https://avatars.githubusercontent.com/chalimar - name: Farzana Prianka + github-handle: role: UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U01FUP87W3U' github: 'https://github.com/FarzanaPrianka' picture: https://avatars.githubusercontent.com/FarzanaPrianka - name: Nandana Rao + github-handle: role: Full Stack Developer links: slack: 'https://hackforla.slack.com/team/U013JA9H62E' github: 'https://github.com/nrrao' picture: https://avatars.githubusercontent.com/nrrao - name: Emerson Castaneda + github-handle: role: Full Stack Developer links: slack: 'https://hackforla.slack.com/team/U01CSPAFEBV' github: 'https://github.com/emecas' picture: https://avatars.githubusercontent.com/emecas - name: Bruce Lai + github-handle: role: Full Stack Developer links: slack: 'https://hackforla.slack.com/team/U01NT0K7XC6' github: 'https://github.com/bruceplai' picture: https://avatars.githubusercontent.com/bruceplai - name: Bhaggyalakshmi Balasubramaniyan + github-handle: role: Full Stack Developer and Tech Lead links: slack: 'https://hackforla.slack.com/team/U01R30YR26L' github: 'https://github.com/bhaggya' picture: https://avatars.githubusercontent.com/bhaggya - name: Ron Fu + github-handle: role: Full Stack Developer links: slack: 'https://hackforla.slack.com/team/UGWDHDF46' github: 'https://github.com/rfvisuals' picture: https://avatars.githubusercontent.com/rfvisuals - name: Isaiah Ozadhe + github-handle: role: Full Stack Developer links: slack: 'https://hackforla.slack.com/team/U034X04V2H5' github: 'https://github.com/Tekkieware' picture: https://avatars.githubusercontent.com/Tekkieware - name: Maxwell Countryman Skewes + github-handle: role: Front End Developer and Tech Lead links: slack: 'https://hackforla.slack.com/team/U01R6RWQR3L' github: 'https://github.com/maxskewes' picture: https://avatars.githubusercontent.com/maxskewes - name: Dennis Chatkhan + github-handle: role: Frontend Developer links: slack: https://hackforla.slack.com/team/U01B4S459CZ github: https://github.com/mealthebear picture: https://avatars.githubusercontent.com/mealthebear - name: Iffath Sultana + github-handle: role: Product Manager links: slack: https://hackforla.slack.com/team/U01JQ2V3NRZ diff --git a/_projects/civic-tech-jobs.md b/_projects/civic-tech-jobs.md index c37a6d8bb2..a59e37c28b 100644 --- a/_projects/civic-tech-jobs.md +++ b/_projects/civic-tech-jobs.md @@ -13,98 +13,90 @@ leadership: slack: https://hackforla.slack.com/team/U010KUGJATC github: https://github.com/kcoronel picture: https://avatars.githubusercontent.com/kcoronel - - name: Salima Yacoubi Soussane - github-handle: - role: Product Manager - links: - slack: https://hackforla.slack.com/team/U03HUJM7YCX - github: https://github.com/Salimays - picture: https://avatars.githubusercontent.com/Salimays - - name: Sabrina Heasley + - name: Kanika Chotani + github-handle: kchotani role: Product Manager links: - slack: https://hackforla.slack.com/team/U05GDBDPEDR - github: https://github.com/sabheasley - picture: https://avatars.githubusercontent.com/sabheasley - - name: Jen Chung - github-handle: - role: UX/UI Design Lead - links: - slack: https://hackforla.slack.com/team/U02A6H5PVAA - github: https://github.com/jenchuu - picture: https://avatars.githubusercontent.com/jenchuu - - name: Melinda Sukosd - role: UX Research Lead - links: - slack: https://hackforla.slack.com/team/U03T1G9F46P - github: https://github.com/melkosm - picture: https://avatars.githubusercontent.com/melkosm - - name: Jenn Wu - github-handle: - role: UX Researcher Lead + slack: https://hackforla.slack.com/team/U02E7ATACAV + github: https://github.com/kchotani + picture: https://avatars.githubusercontent.com/kchotani + - name: Jimmy Juarez + github-handle: JimmyJuarez10 + role: Developer Lead links: - slack: https://hackforla.slack.com/team/U05JS3V38TV - github: https://github.com/jayywu - picture: https://avatars.githubusercontent.com/jayywu - - name: Tin Wei Chung - github-handle: - role: UX/UI Designer - links: - slack: https://hackforla.slack.com/team/U03P6Q6FSQ5 - github: https://github.com/TCUX - picture: https://avatars.githubusercontent.com/TCUX + slack: https://hackforla.slack.com/team/U062FQ7UXQE + github: https://github.com/JimmyJuarez10 + picture: https://avatars.githubusercontent.com/JimmyJuarez10 - name: Lu Feng - github-handle: - role: UX/UI Designer + github-handle: fenglugithub + role: UI/UX Lead links: slack: https://hackforla.slack.com/team/U03NV47TG4X github: https://github.com/fenglugithub picture: https://avatars.githubusercontent.com/fenglugithub - - name: Gabriel Vicencio - github-handle: + - name: Brenda Njemanze + github-handle: brendasdesign + role: UX/UI Designer + links: + slack: https://hackforla.slack.com/team/U06MWMRSCJW + github: https://github.com/brendasdesign + picture: https://avatars.githubusercontent.com/brendasdesign + - name: Armon Brown + github-handle: stanarmon role: UX/UI Designer links: - slack: https://hackforla.slack.com/team/U03P33ZNPGW - github: https://github.com/geibu - picture: https://avatars.githubusercontent.com/geibu + slack: https://hackforla.slack.com/team/U06J0UCAWHE + github: https://github.com/stanarmon + picture: https://avatars.githubusercontent.com/stanarmon + - name: Carmen Mak + github-handle: CarmenMM1 + role: UX/UI Designer + links: + slack: https://hackforla.slack.com/team/U06313EMD41 + github: https://github.com/CarmenMM1 + picture: https://avatars.githubusercontent.com/CarmenMM1 - name: Leah Ellis + github-handle: role: UX Researcher links: slack: https://hackforla.slack.com/team/U04GYTXSP9D github: https://github.com/Leah0996 - picture: https://avatars.githubusercontent.com/Leah0996 - - name: Matt Pereira - github-handle: - role: Developer + picture: https://avatars.githubusercontent.com/Leah0996 + - name: Manju Chawla + github-handle: itsmanjuchawla + role: UX Researcher links: - slack: https://hackforla.slack.com/team/U045XKKB5DH - github: https://github.com/MattPereira - picture: https://avatars.githubusercontent.com/MattPereira + slack: https://hackforla.slack.com/team/U06E9T37H9A + github: https://github.com/itsmanjuchawla + picture: https://avatars.githubusercontent.com/itsmanjuchawla - name: Bitian Zhang + github-handle: role: Developer links: slack: https://hackforla.slack.com/team/U04H6PYK14N github: https://github.com/bzzz-coding picture: https://avatars.githubusercontent.com/bzzz-coding - name: Benny Van + github-handle: role: Developer links: slack: https://hackforla.slack.com/team/U05JP90EHMK github: https://github.com/bennyv8 picture: https://avatars.githubusercontent.com/bennyv8 - - name: Sarah Sanger + - name: Kevin Yu + github-handle: kevin31yu role: Developer links: - slack: https://hackforla.slack.com/team/U02M686LYET - github: https://github.com/Blulady - picture: https://avatars.githubusercontent.com/Blulady - - name: Nga Do - github-handle: - role: UX Researcher + slack: https://hackforla.slack.com/team/U061GQQ56Q4 + github: https://github.com/kevin31yu + picture: https://avatars.githubusercontent.com/kevin31yu + - name: Ida Valenzuela + github-handle: irais-valenzuela + role: Developer links: - slack: https://hackforla.slack.com/team/U05JS3BS9FD - github: https://github.com/ngadoq - picture: https://avatars.githubusercontent.com/ngadoq + slack: https://hackforla.slack.com/team/U062NBBNFA7 + github: https://github.com/irais-valenzuela + picture: https://avatars.githubusercontent.com/irais-valenzuela links: - name: GitHub url: https://github.com/hackforla/civictechjobs @@ -114,14 +106,13 @@ links: url: ../assets/pdfs/Civic-Tech-Jobs-One-Sheet.pdf looking: technologies: - - Django - - Django REST Framework - React - - Webpack - - Babel - - PostgreSQL + - Express + - Node.JS - Docker - - GitHub Actions + - PostgreSQL + - Django + - Figma tools: location: - Remote diff --git a/_projects/civic-tech-structure.md b/_projects/civic-tech-structure.md index 72cb79b506..73b2a2645f 100644 --- a/_projects/civic-tech-structure.md +++ b/_projects/civic-tech-structure.md @@ -11,30 +11,35 @@ alt: "Civic Tech Structure" image-hero: /assets/images/projects/civic-tech-structure-hero.png leadership: - name: Bonnie Wolfe + github-handle: role: Executive Director links: slack: "https://hackforla.slack.com/team/UE1UG1YFP" github: "https://github.com/ExperimentsInHonesty" picture: https://avatars.githubusercontent.com/ExperimentsInHonesty - name: Olivia Chiong + github-handle: role: Director of Operations links: slack: "https://hackforla.slack.com/team/U01GJC7VC6" github: "https://github.com/olivia-chiong" picture: https://avatars.githubusercontent.com/olivia-chiong - name: Sam H. + github-handle: role: Co-Product Manager links: slack: "https://hackforla.slack.com/team/U01A2FPLBC3" github: "https://github.com/MasSamH" picture: https://avatars.githubusercontent.com/MasSamH - name: Thad Kerosky + github-handle: role: Co-Product Manager links: slack: "https://cfa.slack.com/archives/C019RCM15FE" github: "https://github.com/thadk" picture: https://avatars2.githubusercontent.com/u/283343?v=4 - name: Naomi Chao + github-handle: role: Special Projects Coordinator links: slack: "https://hackforla.slack.com/team/U018TQWQB0T" diff --git a/_projects/design-systems.md b/_projects/design-systems.md index 52ff637c51..71e42c996a 100644 --- a/_projects/design-systems.md +++ b/_projects/design-systems.md @@ -11,66 +11,77 @@ alt: 'Design Systems' image-hero: /assets/images/projects/design-systems-hero.jpg leadership: - name: Yasaman Roostaeian + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U033GFQ1UQM' github: 'https://github.com/allthatyazz' picture: 'https://avatars.githubusercontent.com/allthatyazz' - name: Rachel Newcomb + github-handle: role: Lead UX Researcher links: slack: 'https://hackforla.slack.com/team/U03Q5J8SVM3' github: 'https://github.com/rachelita2' picture: 'https://avatars.githubusercontent.com/rachelita2' - name: Sandra Berjan + github-handle: role: Lead Content Designer links: slack: 'https://hackforla.slack.com/team/U03753VQBSR' github: 'https://github.com/sandraberjan' picture: 'https://avatars.githubusercontent.com/sandraberjan' - name: Khanh Cao + github-handle: role: Co-Lead UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U04A19TDBED' github: 'https://github.com/khanhcao17' picture: 'https://avatars.githubusercontent.com/khanhcao17' - name: Debbie Nyasetia + github-handle: role: Co-Lead UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U03FJ3V58FN' github: 'https://github.com/kangina-tech' picture: 'https://avatars.githubusercontent.com/kangina-tech' - name: Wataru Inoue + github-handle: role: UX Consultant links: slack: 'https://hackforla.slack.com/team/U02SMT4H4LR' github: 'https://github.com/winoue90' picture: 'https://avatars.githubusercontent.com/winoue90' - name: Faezeh Faezipour + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U04AT8KU5CY' github: 'https://github.com/fuzjan81' picture: 'https://avatars.githubusercontent.com/fuzjan81' - name: Eva Kwock + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U049PSE3ZMZ' github: 'https://github.com/EvaKw' picture: 'https://avatars.githubusercontent.com/EvaKw' - name: Zeynep Aslan + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U04HDCMD90A' github: 'https://github.com/zeaslan' picture: 'https://avatars.githubusercontent.com/zeaslan' - name: Gala Stojnic + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U03307LRD2A' github: 'https://github.com/GalaStojnic' picture: 'https://avatars.githubusercontent.com/GalaStojnic' - name: Eli Marietta + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U03P6Q87BEZ' @@ -83,18 +94,21 @@ leadership: github: 'https://github.com/TobyShanti' picture: 'https://avatars.githubusercontent.com/TobyShanti' - name: Liz Zheng + github-handle: role: UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U04GYRW4DAT' github: 'https://github.com/liz-zheng' picture: 'https://avatars.githubusercontent.com/liz-zheng' - name: Michael Morgan + github-handle: role: UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U01SPJCC26A' github: 'https://github.com/mklmrgn' picture: 'https://avatars.githubusercontent.com/mklmrgn' - name: Robert Schacht + github-handle: role: Content Designer links: slack: 'https://hackforla.slack.com/team/U02R5GG3T09' diff --git a/_projects/ems-triage-tracker.md b/_projects/ems-triage-tracker.md index a4bd1a3e3f..e9124fd30d 100644 --- a/_projects/ems-triage-tracker.md +++ b/_projects/ems-triage-tracker.md @@ -7,59 +7,68 @@ alt: 'EMS Triage Tracker' image-hero: /assets/images/projects/ems-triage-tracker-hero.png leadership: - name: Bonnie Wolfe + github-handle: role: Agile Coach links: slack: 'https://hackforla.slack.com/team/UE1UG1YFP' github: 'https://github.com/experimentsinhonesty' picture: https://avatars.githubusercontent.com/experimentsinhonesty - name: Dr. Stephen M. Hubbard + github-handle: role: System Design Project Advisor links: slack: 'https://hackforla.slack.com/team/UPXH1Q3RP' github: 'https://github.com/lwanderson-triage' picture: https://avatars.githubusercontent.com/lwanderson-triage - name: Shawn Duenas + github-handle: role: Project Manager, Presentation Build and UX Research links: slack: 'https://hackforla.slack.com/team/UN4EV6CG3' github: 'https://github.com/McRawly' picture: https://avatars.githubusercontent.com/McRawly - name: Simone Wojtaszek + github-handle: role: Lead UX/UI Design and UX Research links: slack: 'https://hackforla.slack.com/team/UNY9Q55B7' github: 'https://github.com/designsimone' picture: https://avatars.githubusercontent.com/designsimone - name: Nicole Doan + github-handle: role: Lead UX/UI Design and UX Research links: slack: 'https://hackforla.slack.com/team/UBPKHJJVC' github: 'https://github.com/nekobox' picture: https://avatars.githubusercontent.com/nekobox - name: Conor McKiernan + github-handle: role: Logo Design and UX Strategy/Research links: slack: 'https://hackforla.slack.com/team/UNHNCALSE' github: 'https://github.com/redmckiernan' picture: https://avatars.githubusercontent.com/redmckiernan - name: Selena Jiang + github-handle: role: UI Design, Life Saving Measures screen links: slack: 'https://hackforla.slack.com/team/UMYN9DVSB' github: 'https://github.com/ysjiang18' picture: https://avatars.githubusercontent.com/ysjiang18 - name: Richa Srivastava + github-handle: role: UX Research links: slack: 'https://hackforla.slack.com/team/UJ8M64E5V' picture: /assets/images/misc/no-photo.png - name: Kelvin Nguyen + github-handle: role: UI Design, Individual Assessment screen links: slack: 'https://hackforla.slack.com/team/UPNR0KG00' picture: /assets/images/misc/no-photo.png -links: - - name: Github +links: + - name: GitHub url: 'https://github.com/hackforla/ems-triage-tracker' - name: Slack url: 'https://hackforla.slack.com/archives/CQ5J1DA72' @@ -67,15 +76,15 @@ links: url: 'https://drive.google.com/file/d/1WWxADa3aBKtTk47Fx1vzoMSn0-yWKp3X/view?usp=sharing' - name: Overview url: '../assets/pdfs/EMS-Triage-Tracker-One-Sheet.pdf' -location: +location: - Downtown LA partner: General Assembly (Downtown Campus), Lisa W. Anderson -tools: +tools: - Figma - video production -program-area: +program-area: - Civic Tech Infrastructure status: Completed visible: true completed-contact: team@hackforla.org ---- \ No newline at end of file +--- diff --git a/_projects/engage.md b/_projects/engage.md index 9f84254c5f..9a4005970b 100644 --- a/_projects/engage.md +++ b/_projects/engage.md @@ -7,24 +7,28 @@ alt: 'Engage' image-hero: /assets/images/projects/engage-hero.png leadership: - name: Bonnie Wolfe + github-handle: role: Agile Coach links: slack: 'https://hackforla.slack.com/team/UE1UG1YFP' github: 'https://github.com/ExperimentsInHonesty' picture: 'https://avatars.githubusercontent.com/ExperimentsInHonesty' - name: Ryan Mayott + github-handle: role: UI/UX Designer links: slack: 'https://hackforla.slack.com/team/U01L3BJ3QSW' github: 'https://github.com/rmayott' picture: 'https://avatars.githubusercontent.com/rmayott' - name: Bryon Heart + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U01GHT3EMNZ' github: 'https://github.com/BryonPm' picture: 'https://avatars.githubusercontent.com/BryonPm' - name: Eli Selkin + github-handle: role: Backend Architect and Technology Lead links: slack: 'https://hackforla.slack.com/team/U0611PL2D' diff --git a/_projects/expunge-assist.md b/_projects/expunge-assist.md index 1d3a882f0d..201b53574f 100644 --- a/_projects/expunge-assist.md +++ b/_projects/expunge-assist.md @@ -1,12 +1,18 @@ --- identification: '218391110' title: Expunge Assist -description: 'Expunge Assist aims to help people in California with criminal records accomplish record clearance, expungement or reduction and subsequently a second chance as a part of society. -

    We work with verifiable non-profits, the government and partners to build digital tools that can affect changes in the lives of these justice impacted individuals.' +description: 'Expunge Assist is a free digital tool designed to aid Californians with arrest and conviction histories in clearing their criminal records. A personal statement is the most important proof of rehabilitation filed with an expungement petition. Our letter generator helps people write their statements to the court. The tool does not rely on AI, protects personal privacy, and does not store sensitive information. Community organizers, government agencies, and legal advocates in the clean slate and criminal justice fields are making an incredible impact. Expunge Assist aims to support that work.' image: /assets/images/projects/expunge-assist.png alt: 'Expunge Assist' image-hero: /assets/images/projects/expunge-assist-hero.png leadership: + - name: Maria Weissman + github-handle: mariaweissman + role: Product Manager, Project Manager + links: + slack: https://hackforla.slack.com/team/U06REA9H3FF + github: https://github.com/mariaweissman + picture: https://avatars.githubusercontent.com/mariaweissman - name: Analicia Mejia Mesinas github-handle: amejiamesinas role: Product Manager, UX Research @@ -14,20 +20,6 @@ leadership: slack: https://hackforla.slack.com/team/U04J34E73CG github: https://github.com/amejiamesinas picture: https://avatars.githubusercontent.com/amejiamesinas - - name: Lane Mitchell - github-handle: lmitch10 - role: Product Manager, Development - links: - slack: https://hackforla.slack.com/team/U052LEP0BSN - github: https://github.com/lmitch10 - picture: https://avatars.githubusercontent.com/lmitch10 - - name: Curtis Barber - github-handle: CBx3000 - role: Product Manager, Content - links: - slack: https://hackforla.slack.com/team/U05RZAETCQ4 - github: https://github.com/CBx3000 - picture: https://avatars.githubusercontent.com/CBx3000 - name: Mireya V. Aviles github-handle: vanessaavviles role: Product Manager, Design @@ -58,20 +50,38 @@ leadership: picture: https://avatars.githubusercontent.com/jyehllow - name: Samantha Hyler github-handle: SamHyler - role: UX Content, Team Lead + role: UX Content, Team Co-lead links: slack: https://hackforla.slack.com/team/U025XR6MY6S github: https://github.com/SamHyler picture: https://avatars.githubusercontent.com/SamHyler + - name: Emma Thrash + github-handle: emmathrash + role: UX Content, Team Co-lead + links: + slack: https://hackforla.slack.com/team/U05JUM3881J + github: https://github.com/emmathrash + picture: https://avatars.githubusercontent.com/emmathrash + - name: Sylvia Nam + github-handle: sylvia-nam + role: UX Research, Team Lead + links: + slack: https://hackforla.slack.com/team/U06E9RQ8DRA + github: https://github.com/sylvia-nam + picture: https://avatars.githubusercontent.com/sylvia-nam links: + - name: Overview + url: '../assets/pdfs/Expunge-Assist-One-Sheet.pdf' - name: GitHub url: 'https://github.com/hackforla/record-clearance/' + - name: Wiki + url: 'https://github.com/hackforla/expunge-assist/wiki' - name: Site url: https://expungeassist.org/ - name: Readme url: 'https://github.com/hackforla/record-clearance/blob/master/README.md' - name: Slack - url: 'https://hackforla.slack.com/messages/CN8NXTPK5' + url: 'https://hackforla.slack.com/archives/CN8NXTPK5' looking: - category: Marketing skill: Marketing & Communications @@ -86,6 +96,13 @@ technologies: location: # - Santa Monica - Remote +tools: + - Figma + - Miro + - Zoom + - Google Suite + - FigJam + - LettuceMeet visible: true program-area: - Justice diff --git a/_projects/food-oasis.md b/_projects/food-oasis.md index d768d83397..8497d5047e 100644 --- a/_projects/food-oasis.md +++ b/_projects/food-oasis.md @@ -7,24 +7,35 @@ alt: 'Food Oasis' image-hero: /assets/images/projects/food-oasis-hero.jpg leadership: - name: John Darragh + github-handle: role: Lead Developer links: slack: "https://hackforla.slack.com/team/UFLDX9V19" github: "https://github.com/entrotech" picture: https://avatars.githubusercontent.com/entrotech + - name: Hannah Zulueta + github-handle: + role: Lead Developer + links: + slack: "https://hackforla.slack.com/team/U9SCMTNK0" + github: "https://github.com/hanapotski" + picture: https://avatars.githubusercontent.com/hanapotski - name: Bryan Wu + github-handle: role: UX/UR Lead links: slack: "https://hackforla.slack.com/team/U01PG6RD0T1" github: "https://github.com/fancyham" picture: https://avatars.githubusercontent.com/fancyham - name: Gigi Patel + github-handle: role: Lead UX Researcher links: slack: "https://hackforla.slack.com/team/U02KZ8WSHHV" github: "https://github.com/GigiUxR" picture: https://avatars.githubusercontent.com/GigiUxR - name: Virginia Wu + github-handle: role: Full Stack Engineer links: slack: "https://hackforla.slack.com/team/U02G7SBKSV7" @@ -51,12 +62,28 @@ leadership: slack: https://hackforla.slack.com/team/U03UWG0EP7V github: https://github.com/junjun107 picture: https://avatars.githubusercontent.com/junjun107 - - name: Hannah Zulueta - role: Lead Developer + - name: Krista Strucke + github-handle: kurikurichan + role: Full Stack Engineer links: - slack: "https://hackforla.slack.com/team/U9SCMTNK0" - github: "https://github.com/hanapotski" - picture: https://avatars.githubusercontent.com/hanapotski + slack: https://hackforla.slack.com/team/U04PHV2HUF6 + github: https://github.com/kurikurichan + picture: https://avatars.githubusercontent.com/kurikurichan + - name: Qiqi Zheng + github-handle: qiqicodes + role: Full Stack Engineer + links: + slack: https://hackforla.slack.com/team/U01LM6SE70A + github: https://github.com/qiqicodes + picture: https://avatars.githubusercontent.com/qiqicodes + - name: Saumil Dhankar + github-handle: saumildhankar + role: Full Stack Engineer + links: + slack: https://hackforla.slack.com/team/U02AG2K2BB3 + github: https://github.com/saumildhankar + picture: https://avatars.githubusercontent.com/saumildhankar + links: - name: GitHub @@ -108,4 +135,4 @@ status: Active iframe: available: true src: "https://la.foodoasis.net/widget" ---- +--- \ No newline at end of file diff --git a/_projects/guides-team.md b/_projects/guides-team.md index d7323d46c7..56ae214534 100644 --- a/_projects/guides-team.md +++ b/_projects/guides-team.md @@ -15,17 +15,26 @@ leadership: github: 'https://github.com/ExperimentsInHonesty' picture: https://avatars.githubusercontent.com/ExperimentsInHonesty - name: Sarah Edwards + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U03KBU16APN' github: 'https://github.com/edwardsarah' picture: https://avatars.githubusercontent.com/edwardsarah - - name: Sarah Levine + - name: Ayma Rahman + github-handle: aymarmsba role: Product Manager links: - slack: 'https://hackforla.slack.com/team/U05RWQJ8YKU' - github: 'https://github.com/levines2017' - picture: https://avatars.githubusercontent.com/levines2017 + slack: https://hackforla.slack.com/team/U06C183Q2HL + github: https://github.com/aymarmsba + picture: https://avatars.githubusercontent.com/aymarmsba + - name: Mary Gabrielian + github-handle: marygabrielian + role: Product Manager + links: + slack: https://hackforla.slack.com/team/U06KMNL8ETY + github: https://github.com/marygabrielian + picture: https://avatars.githubusercontent.com/marygabrielian - name: Rhoda Michael github-handle: the-techgurl role: UX Research Lead @@ -33,6 +42,20 @@ leadership: slack: 'https://hackforla.slack.com/team/U05JS9NLNQJ' github: 'https://github.com/the-techgurl' picture: https://avatars.githubusercontent.com/the-techgurl + - name: Aditya Soni + github-handle: Aditya23soni + role: Product Manager + links: + slack: https://hackforla.slack.com/team/U07F766J29M + github: https://github.com/Aditya23soni + picture: https://avatars.githubusercontent.com/Aditya23soni + - name: Jesus Diaz + github-handle: JesseTheCleric + role: Product Manager + links: + slack: https://hackforla.slack.com/team/U0725MRMMA9 + github: https://github.com/JesseTheCleric + picture: https://avatars.githubusercontent.com/JesseTheCleric links: - name: GitHub url: 'https://github.com/hackforla/guides' diff --git a/_projects/heart.md b/_projects/heart.md index 7fa897572a..e11b12bbf0 100644 --- a/_projects/heart.md +++ b/_projects/heart.md @@ -7,51 +7,60 @@ alt: 'Heart' image-hero: /assets/images/projects/heart-hero.png leadership: - name: Marie-Aimee Brajeux + github-handle: role: Product Manager links: linkedin: https://linkedin.com/in/marie-aim%C3%A9e-brajeux-88b40978/ picture: https://user-images.githubusercontent.com/37763229/79702509-34a33480-825a-11ea-94e8-ff952f42863d.jpg - name: Adrian Inchauste + github-handle: role: Design Sprint Facilitator links: linkedin: https://linkedin.com/in/adrianinchauste picture: https://user-images.githubusercontent.com/37763229/79702530-63210f80-825a-11ea-8314-93950014939d.jpg - name: Jason LaManque + github-handle: role: Design Sprint Facilitator links: linkedin: https://www.linkedin.com/in/jasonlamanque/ picture: https://user-images.githubusercontent.com/37763229/79702551-9a8fbc00-825a-11ea-819f-dde8cad5d058.jpg - name: Lex Roman + github-handle: role: UX Advisor (1st stage) links: linkedin: https://linkedin.com/in/lexroman/ github: https://github.com/calexity picture: https://avatars0.githubusercontent.com/u/1103366?s=400&u=3b85c9e08f73d0980caf99bf0e6ee005f8da925a&v=4 - name: Gian Reyes Dionisio + github-handle: role: UX Design Lead links: linkedin: https://linkedin.com/in/gianreyesdionisio/ github: https://github.com/gianbun picture: https://avatars3.githubusercontent.com/u/45775543?s=400&v=4 - name: Charlotte Soestini + github-handle: role: UX Design and Documentarian (post project) links: linkedin: https://linkedin.com/in/charlotte-soestini github: https://github.com/charlottesauce picture: https://avatars2.githubusercontent.com/u/45779646?s=400&v=4 - name: Bonnie Wolfe + github-handle: role: Documentarian (post project) links: linkedin: https://linkedin.com/in/bonnieawolfe github: https://github.com/experimentsinhonesty picture: https://avatars2.githubusercontent.com/u/37763229?s=400&u=e7cb79276f78b9fb641dac9c3540fd4301a16958&v=4 - name: Roland Abregorivas + github-handle: role: Tech Lead links: linkedin: https://linkedin.com/in/rolandabregorivas github: https://github.com/abregorivas picture: https://avatars2.githubusercontent.com/u/7821047?s=400&u=9128a4d0a4d1ff33bdebae02bcdaac7ff7e7432f&v=4 - name: Tien Yuan + github-handle: role: Tech Lead links: linkedin: https://linkedin.com/in/tienyuan/ @@ -61,7 +70,7 @@ links: - name: GitHub url: 'https://github.com/hackforla/heart' - name: Slack - url: 'https://hackforla.slack.com/messages/CDWKEBYBB' + url: 'https://hackforla.slack.com/archives/CDWKEBYBB' - name: Wiki url: 'https://github.com/hackforla/heart/wiki' partner: LA City & County Attorney’s Homeless Engagement and Response Team diff --git a/_projects/hellogov.md b/_projects/hellogov.md index f2635e2c3b..7fc19f1169 100644 --- a/_projects/hellogov.md +++ b/_projects/hellogov.md @@ -17,6 +17,7 @@ leadership: github: 'https://github.com/seport' picture: https://avatars.githubusercontent.com/seport - name: Brett Beekley + github-handle: links: slack: 'https://hackforla.slack.com/team/USRRN73NE' github: 'https://github.com/beekley' @@ -29,7 +30,7 @@ links: - name: Readme url: 'https://github.com/helloGov/webapp/blob/master/README.md' - name: Slack - url: 'https://hackforla.slack.com/messages/CDA23KHKP' + url: 'https://hackforla.slack.com/archives/CDA23KHKP' looking: location: # - Santa Monica diff --git a/_projects/home-unite-us.md b/_projects/home-unite-us.md index f05dc40bb3..fad1a6fe13 100644 --- a/_projects/home-unite-us.md +++ b/_projects/home-unite-us.md @@ -7,101 +7,110 @@ alt: 'Home Unite Us' image-hero: /assets/images/projects/home-unite-us-hero.png leadership: - name: Tyler Thome + github-handle: role: HUU Tech Lead links: slack: "https://hackforla.slack.com/team/ULN1M6UAH" github: "https://github.com/tylerthome" picture: https://avatars.githubusercontent.com/tylerthome - name: Jed Stewart + github-handle: role: Developer links: slack: "https://hackforla.slack.com/team/U04A3J6V0HY" github: "https://github.com/jed-stewart" picture: https://avatars.githubusercontent.com/jed-stewart - name: Mira Kinebuchi + github-handle: role: Developer links: slack: "https://hackforla.slack.com/team/U0411CAL13N" github: "https://github.com/mira-kine" picture: https://avatars.githubusercontent.com/mira-kine - name: Stephen Barkley-Yeung + github-handle: role: Developer links: slack: "https://hackforla.slack.com/team/U041403GHEC" github: "https://github.com/stevbark" picture: https://avatars.githubusercontent.com/stevbark - name: Erik Guntner + github-handle: role: Front End Developer links: slack: "https://hackforla.slack.com/team/U0103MJB0AZ" github: "https://github.com/erikguntner" picture: https://avatars.githubusercontent.com/erikguntner - - name: Kristelle Gumaru - role: Product Manager - links: - slack: "https://hackforla.slack.com/team/U031VJ99ATU" - github: "https://github.com/K-Gumarama" - picture: https://avatars.githubusercontent.com/K-Gumarama - name: Sanya Nijhawan - role: Product Manager + github-handle: sanya301 + role: Advisory links: - slack: "https://hackforla.slack.com/team/U031FLYS561" - github: "https://github.com/sanya301" + slack: https://hackforla.slack.com/team/U031FLYS561 + github: https://github.com/sanya301 picture: https://avatars.githubusercontent.com/sanya301 - name: Raji Pradheap + github-handle: role: Product Manager links: slack: "https://hackforla.slack.com/team/U02R9MKA6KH" github: "https://github.com/rpradheap" picture: https://avatars.githubusercontent.com/rpradheap - name: Bryce Lednar + github-handle: role: Product Manager links: slack: "https://hackforla.slack.com/team/U049TSDG2SX" github: "https://github.com/brycelednar" picture: https://avatars.githubusercontent.com/brycelednar - - name: Farah Khan - role: UX/UI Designer - links: - slack: "https://hackforla.slack.com/team/U01JC8VEKMH" - github: "https://github.com/fourmatte" - picture: https://avatars.githubusercontent.com/fourmatte - name: Eduardo De La Rosa + github-handle: role: UX/UI Designer links: slack: "https://hackforla.slack.com/team/U0430G2T4AC" github: "https://github.com/edela0015" picture: https://avatars.githubusercontent.com/edela0015 - name: Flora Osmond + github-handle: role: UX/UI Designer links: slack: "https://hackforla.slack.com/team/U047ZT4GP5E" github: "https://github.com/itzflowa" picture: https://avatars.githubusercontent.com/itzflowa - name: Rachel Bracker + github-handle: role: Design Lead links: slack: "https://hackforla.slack.com/team/U02JQLQ6YGY" github: "https://github.com/rpbracker" picture: https://avatars.githubusercontent.com/rpbracker - name: Samuel Kowitch + github-handle: role: UX/UI Designer links: slack: "https://hackforla.slack.com/team/U04GYSFB98X" github: "https://github.com/KowDesign" picture: https://avatars.githubusercontent.com/KowDesign - name: Muyin Zheng + github-handle: role: UX/UI Designer links: slack: "https://hackforla.slack.com/team/U04HAEEKT29" github: "https://github.com/IndigoYinZ" picture: https://avatars.githubusercontent.com/IndigoYinZ - name: Emily Eldar + github-handle: role: Developer links: slack: "https://hackforla.slack.com/team/U04BEDM1B2L" github: "https://github.com/emeldar" picture: https://avatars.githubusercontent.com/emeldar + - name: Lola Sarumi + github-handle: lola3736 + role: Lead Product / Project + links: + slack: https://hackforla.slack.com/team/U06TAL88YUV + github: https://github.com/lola3736 + picture: https://avatars.githubusercontent.com/lola3736 links: - name: GitHub url: "https://github.com/hackforla/homeuniteus" diff --git a/_projects/public-tree-map.md b/_projects/public-tree-map.md index 866ab62f5e..b9c694b074 100644 --- a/_projects/public-tree-map.md +++ b/_projects/public-tree-map.md @@ -31,7 +31,7 @@ links: - name: Test Site url: 'http://public-tree-map.surge.sh/' - name: Slack - url: 'https://hackforla.slack.com/messages/C9UU5KKAA/' + url: 'https://hackforla.slack.com/archives/C9UU5KKAA/' - name: Readme url: 'https://github.com/Public-Tree-Map/public-tree-map/blob/master/README.md' technologies: diff --git a/_projects/tdm-calculator.md b/_projects/tdm-calculator.md index 4d4d0b0c9b..55228c5614 100644 --- a/_projects/tdm-calculator.md +++ b/_projects/tdm-calculator.md @@ -7,35 +7,75 @@ alt: 'LA TDM Calculator' image-hero: /assets/images/projects/TDM-calculator-hero.png leadership: - name: Bonnie Wolfe + github-handle: role: Agile Coach / Primary Stakeholder Relationship Manager links: slack: 'https://hackforla.slack.com/team/DE1HK083W' github: 'https://github.com/ExperimentsInHonesty' picture: https://avatars.githubusercontent.com/ExperimentsInHonesty - name: John Darragh + github-handle: role: Architect links: slack: 'https://hackforla.slack.com/team/UFLDX9V19' github: 'https://github.com/entrotech' picture: https://avatars.githubusercontent.com/entrotech - name: Ebi Imafidon + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U031EU2E6LB' github: 'https://github.com/Biuwa' picture: https://avatars.githubusercontent.com/Biuwa + - name: Parisa Jannatifard + github-handle: Parisajf + role: Product Manager + links: + slack: https://hackforla.slack.com/team/U05Q5D34ARZ + github: https://github.com/Parisajf + picture: https://avatars.githubusercontent.com/Parisajf - name: Anousha Shadrach + github-handle: role: UX Designer links: slack: 'https://hackforla.slack.com/team/U045EHW8NDA' github: 'https://github.com/Noushie' picture: https://avatars.githubusercontent.com/Noushie - name: Jane He + github-handle: role: Lead, UX Research links: slack: 'https://hackforla.slack.com/team/U01RDSRT46R' github: 'https://github.com/Jane4925' picture: https://avatars.githubusercontent.com/Jane4925 + - name: Nilakshi Sahai + github-handle: NilakshiS + role: UX Design Lead + links: + slack: https://hackforla.slack.com/team/U06SYVD69L7 + github: https://github.com/NilakshiS + picture: https://avatars.githubusercontent.com/NilakshiS + - name: Heejung Hong + github-handle: heejung-hong + role: Front End Development Lead + links: + slack: https://hackforla.slack.com/team/U064M7X48SY + github: https://github.com/heejung-hong + picture: https://avatars.githubusercontent.com/heejung-hong + - name: Marlena Mellody Khim-Sai + github-handle: marlenamellody + role: UX Design Lead + links: + slack: https://hackforla.slack.com/team/U06DSRCSXRD + github: https://github.com/marlenamellody + picture: https://avatars.githubusercontent.com/marlenamellody + - name: Melissa Perry + github-handle: melissaperry09 + role: UX Research Lead + links: + slack: https://hackforla.slack.com/team/U05MCJTTPN3 + github: https://github.com/melissaperry09 + picture: https://avatars.githubusercontent.com/melissaperry09 links: - name: GitHub url: 'https://github.com/hackforla/tdm-calculator' diff --git a/_projects/tech-work-experience.md b/_projects/tech-work-experience.md index 6df359f6f0..18965aba4d 100644 --- a/_projects/tech-work-experience.md +++ b/_projects/tech-work-experience.md @@ -6,43 +6,50 @@ image: /assets/images/projects/tech-work-experience.png alt: 'Tech Work Experience' image-hero: /assets/images/projects/tech-work-experience-hero.png leadership: - - name: Priyanka Talwar + - name: Priyanka Talwar + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U029P91EY15' github: 'https://github.com/priyatalwar' picture: https://avatars.githubusercontent.com/priyatalwar - name: Joshua Fishman + github-handle: role: Product Manager - Engineering links: slack: 'https://hackforla.slack.com/team/U041G3Y141W' github: 'https://github.com/joshfishman' picture: https://avatars.githubusercontent.com/joshfishman - name: Yingjie Ou + github-handle: role: UX Research Lead links: slack: 'https://hackforla.slack.com/team/U03TP1VFALV' github: 'https://github.com/pandanista' picture: https://avatars.githubusercontent.com/pandanista - name: Hyun Joo Sandy Oh + github-handle: role: UX Research Co-Lead links: slack: 'https://hackforla.slack.com/team/U03RZE7TTKP' github: 'https://github.com/doctorsandy' picture: https://avatars.githubusercontent.com/doctorsandy - name: Sara Brady + github-handle: role: UX Research Co-Lead links: slack: 'https://hackforla.slack.com/team/U0371AXAVUN' github: 'https://github.com/bradyse' picture: https://avatars.githubusercontent.com/bradyse - name: Andrew Salvatore + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U04K5R2A7L2' github: 'https://github.com/AndrewSalvatore' picture: https://avatars.githubusercontent.com/AndrewSalvatore - name: Angela Darosh + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U03J4ENS09F' @@ -55,36 +62,42 @@ leadership: github: 'https://github.com/bryannalim' picture: https://avatars.githubusercontent.com/bryannalim - name: Brian Dick + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U046AAZD309' github: 'https://github.com/dialectic51' picture: https://avatars.githubusercontent.com/dialectic51 - name: Jessie Liu + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U045YQFSGMB' github: 'https://github.com/jessieliu1219' picture: https://avatars.githubusercontent.com/jessieliu1219 - name: Minji Kim + github-handle: role: UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U02ST1L9WAH' github: 'https://github.com/meetminji' picture: https://avatars.githubusercontent.com/meetminji - name: Natalie Aguilar + github-handle: role: UX/UI Designer links: slack: 'https://hackforla.slack.com/team/U04P6N186P9' github: 'https://github.com/Natalie-Aguilar' picture: https://avatars.githubusercontent.com/Natalie-Aguilar - name: Nino Dzotsenidze + github-handle: role: UX Researcher links: slack: 'https://hackforla.slack.com/team/U04MUEYTECR' github: 'https://github.com/Dzotsen' picture: https://avatars.githubusercontent.com/Dzotsen - name: Eric Vennemeyer + github-handle: role: Developer links: slack: 'https://hackforla.slack.com/team/U03AUUZT3E3' @@ -92,10 +105,10 @@ leadership: picture: https://avatars.githubusercontent.com/ericvennemeyer links: - - name: Github + - name: GitHub url: 'https://github.com/hackforla/internship' - name: Slack - url: 'https://hackforla.slack.com/messages/C01VAUPU788' + url: 'https://hackforla.slack.com/archives/C01VAUPU788' - name: Wiki url: 'https://github.com/hackforla/internship/wiki' - name: Overview @@ -124,4 +137,4 @@ program-area: - Workforce Development status: Active visible: true ---- \ No newline at end of file +--- diff --git a/_projects/vrms.md b/_projects/vrms.md index f395057200..bb0b20585c 100644 --- a/_projects/vrms.md +++ b/_projects/vrms.md @@ -24,6 +24,13 @@ leadership: slack: 'https://hackforla.slack.com/team/U03K7Q1FV3P' github: 'https://github.com/JudyLee533' picture: 'https://avatars.githubusercontent.com/JudyLee533' + - name: Jack Haeger + github-handle: JackHaeg + role: Lead Product Manager + links: + slack: https://hackforla.slack.com/team/U059005TN1L + github: https://github.com/JackHaeg + picture: https://avatars.githubusercontent.com/JackHaeg - name: Alex Lee role: Product Manager links: @@ -31,6 +38,7 @@ leadership: github: 'https://github.com/heyitsalexander' picture: 'https://avatars.githubusercontent.com/heyitsalexander' - name: Amanda Glover + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/U042G8B7RB3' diff --git a/_projects/website.md b/_projects/website.md index a97e759ae1..d294474410 100644 --- a/_projects/website.md +++ b/_projects/website.md @@ -12,72 +12,31 @@ leadership: slack: 'https://hackforla.slack.com/team/UE1UG1YFP' github: 'https://github.com/ExperimentsInHonesty' picture: https://avatars.githubusercontent.com/ExperimentsInHonesty - - name: Anjola Jaiyeola - role: Product Team + - name: Kelly Chuang + github-handle: kellyc9 + role: Product Manager links: - slack: https://hackforla.slack.com/team/U052HJ1NMEZ - github: https://github.com/anjolaaoluwa - picture: https://avatars.githubusercontent.com/u/122532788?v=4 - - name: Roslyn Wythe - role: Dev Lead - links: - slack: 'https://hackforla.slack.com/team/U046PD8UT55' - github: 'https://github.com/roslynwythe' - picture: https://avatars.githubusercontent.com/roslynwythe - - name: Sarah Sanger - role: Merge Team - links: - slack: 'https://hackforla.slack.com/team/U02M686LYET' - github: 'https://github.com/blulady' - picture: https://avatars.githubusercontent.com/blulady + slack: https://hackforla.slack.com/team/U06REBB5K4M + github: https://github.com/kellyc9 + picture: https://avatars.githubusercontent.com/kellyc9 - name: Will Gillis - role: Merge Team + role: Developer Co-Lead links: slack: 'https://hackforla.slack.com/team/U043LGHSZFT' github: 'https://github.com/t-will-gillis' picture: https://avatars.githubusercontent.com/t-will-gillis - - name: Danny Do - role: Merge Team - links: - slack: 'https://hackforla.slack.com/team/U048G8S2YAK' - github: 'https://github.com/Adastros' - picture: https://avatars.githubusercontent.com/Adastros - - name: Christina Or - role: Merge Team - links: - slack: 'https://hackforla.slack.com/team/U04J1GBA6QP' - github: 'https://github.com/christinaor' - picture: https://avatars.githubusercontent.com/christinaor - - name: Drake Nguyen - role: Merge Team + - name: Roslyn Wythe + role: Developer Co-Lead links: - slack: https://hackforla.slack.com/team/U04TSESVB4J - github: https://github.com/drakenguyen4000 - picture: https://avatars.githubusercontent.com/drakenguyen4000 + slack: 'https://hackforla.slack.com/team/U046PD8UT55' + github: 'https://github.com/roslynwythe' + picture: https://avatars.githubusercontent.com/roslynwythe - name: Ren Demeis-Ortiz role: Merge Team links: slack: https://hackforla.slack.com/team/U059K7A1VFB github: https://github.com/LRenDO picture: https://avatars.githubusercontent.com/LRenDO - - name: Ronald Paek - role: Merge Team - links: - slack: 'https://hackforla.slack.com/team/U04RS2BCESX' - github: 'https://github.com/ronaldpaek' - picture: https://avatars.githubusercontent.com/ronaldpaek - - name: Richard Kwang - role: Merge Team - links: - slack: https://hackforla.slack.com/team/U04U531MS5P - github: https://github.com/kwangric - picture: https://avatars.githubusercontent.com/kwangric - - name: Adrian Ang - role: Merge Team - links: - slack: 'https://hackforla.slack.com/team/U0596J2AZEE' - github: 'https://github.com/adrianang' - picture: https://avatars.githubusercontent.com/adrianang - name: J Pham github-handle: jphamtv role: Merge Team @@ -92,13 +51,20 @@ leadership: slack: 'https://hackforla.slack.com/team/U04MJA414LU' github: 'https://github.com/Thinking-Panda' picture: https://avatars.githubusercontent.com/Thinking-Panda - - name: Nayan Bhatt - github-handle: freaky4wrld + - name: Danielle Hanson Aras + github-handle: role: Merge Team links: - slack: 'https://hackforla.slack.com/team/U05TZLLJAUV' - github: 'https://github.com/freaky4wrld' - picture: https://avatars.githubusercontent.com/freaky4wrld + slack: 'https://hackforla.slack.com/team/U076DT96PUJ' + github: 'https://github.com/daras-cu' + picture: https://avatars.githubusercontent.com/daras-cu + - name: Samhitha Kamma + github-handle: Samhitha444 + role: Product Manager + links: + slack: https://hackforla.slack.com/team/U07FF529MU6 + github: https://github.com/Samhitha444 + picture: https://avatars.githubusercontent.com/Samhitha444 links: - name: Wiki url: 'https://github.com/hackforla/website/wiki' diff --git a/_projects/youthjusticenav.md b/_projects/youthjusticenav.md index 7fc810f468..753c259c35 100644 --- a/_projects/youthjusticenav.md +++ b/_projects/youthjusticenav.md @@ -31,6 +31,7 @@ leadership: github: 'https://github.com/doctorsandy' picture: 'https://avatars.githubusercontent.com/doctorsandy' - name: Moji Jimoh + github-handle: role: Product Manager links: slack: 'https://hackforla.slack.com/team/D04HDM7DM18' diff --git a/_sass/components/_communities-of-practice.scss b/_sass/components/_communities-of-practice.scss index 922607ea06..c8e7eda2fe 100644 --- a/_sass/components/_communities-of-practice.scss +++ b/_sass/components/_communities-of-practice.scss @@ -130,13 +130,12 @@ } -//styling for join slack and view github buttons +//styling for join Slack and view github buttons .page-card-content{ .link-buttons{ display: flex; justify-content: space-around; flex-wrap: wrap; - } .button-icon{ diff --git a/_sass/components/_project-page.scss b/_sass/components/_project-page.scss index b80f47aa3a..a5acece8c8 100644 --- a/_sass/components/_project-page.scss +++ b/_sass/components/_project-page.scss @@ -264,6 +264,7 @@ background: $color-whitesmoke; border-radius: 0px 0px 10px 10px; height: 80%; + text-align: left; @media #{$bp-below-tablet} { padding-top: 0px; @@ -347,6 +348,11 @@ } } +.resource-img svg { + width: 101px; + height: 101px; +} + .resource-img-provided { padding: 5px; } @@ -394,7 +400,7 @@ @media #{$bp-below-mobile} { min-width: 100%; display: flex; - flex-direction: column; + flex-direction: row; width: auto; justify-content: center; align-content: center; @@ -416,6 +422,7 @@ justify-content: center; align-content: center; align-items: flex-start; + flex: 1; } } diff --git a/_sass/components/_toolkit.scss b/_sass/components/_toolkit.scss index 5ae0e700bb..ebada21cd4 100644 --- a/_sass/components/_toolkit.scss +++ b/_sass/components/_toolkit.scss @@ -61,8 +61,11 @@ flex-direction: column; .filter-tag { - overflow-x: auto; + overflow-x: hidden; overflow-y: hidden; + text-overflow: ellipsis; + white-space: nowrap; + max-width: 300px; } a { @@ -101,6 +104,17 @@ margin: 0 auto; } +[data-article-type="development"] .resource-svg-icons svg{ + width: 50%; + height: 50%; +} + +[data-article-type="development"] .toolkit-flex-item-img-container{ + display: flex; + align-items: center; + justify-content: center; +} + .toolkit-info-container { margin: 1rem 0rem 3.5rem; padding: 0rem 2rem; diff --git a/_sass/elements/_containers.scss b/_sass/elements/_containers.scss index 1ca74ed040..18e385594b 100644 --- a/_sass/elements/_containers.scss +++ b/_sass/elements/_containers.scss @@ -26,6 +26,7 @@ .sub-p { margin-top: 1rem; + width: 100%; } } diff --git a/_sass/elements/_dropdown_filters.scss b/_sass/elements/_dropdown_filters.scss index 07a2a89858..44fd5a66bd 100644 --- a/_sass/elements/_dropdown_filters.scss +++ b/_sass/elements/_dropdown_filters.scss @@ -12,8 +12,9 @@ // Centered Components and filters up top section.filter-content-container { display: flex; - justify-content: center; + justify-content: center; } + .page-contain.projects-inner { margin: 0px 0px; } @@ -31,11 +32,19 @@ a.filter-item { .filter-toolbar { padding: 8px 32px; box-sizing: border-box; - height: 100%; + height: calc(100vh - 60px); + position: sticky; + flex-shrink: 0; + top: 64px; + bottom: 0; + overflow-y: auto; + overflow-x: hidden; + overscroll-behavior: contain; } .filtersDiv { min-width:330px; + padding-bottom: 300px; } //filter container @@ -115,10 +124,12 @@ ul.filter-list li ul li { .dropdown.show-all li.view-all:last-child { display: none; } + .dropdown.show-all { max-height: 360px; overflow-y: scroll; } + .dropdown.show-all li:nth-child(n+9) { display: block; } @@ -197,9 +208,10 @@ border-radius: 2.5px; font-size: 15px; text-transform: capitalize; - &::after { + &::before { content: "\00d7"; - padding-left: 0.5em; + padding-left: 0.75em; + float: right; } &:hover, @@ -243,10 +255,19 @@ a.clear-filter-tags { .scroll-lock { overflow: hidden; } + .filter-toolbar { background-color: $color-pink; + height: 100%; + position: static; padding: 0; } + + .filtersDiv { + padding-bottom: 0px; + padding-top: 0px; + } + .filter-toolbar.show-filters { height: 100vh; width: 100vw; @@ -342,5 +363,4 @@ a.clear-filter-tags { .show-none + .dropdown li { display: block; } - } diff --git a/_sass/elements/_old_dropdown_filters.scss b/_sass/elements/_old_dropdown_filters.scss index 2ebc5734d2..c673ad0631 100644 --- a/_sass/elements/_old_dropdown_filters.scss +++ b/_sass/elements/_old_dropdown_filters.scss @@ -168,7 +168,7 @@ a.old-clear-filter-tags { } } -@media (max-width: 659px) { +@media #{$bp-below-desktop-medium} { //creating 2 rows and 2 columns to display categories on mobile ul.old-filter-list { display: grid; diff --git a/_sass/elements/_search-bar.scss b/_sass/elements/_search-bar.scss index 77fbb0b8f3..f10840eed3 100644 --- a/_sass/elements/_search-bar.scss +++ b/_sass/elements/_search-bar.scss @@ -10,6 +10,18 @@ margin-bottom: 10px; } +form#search-bar { + position: sticky; + padding: 10px; + top: 60px; + z-index: 10; +} +// // Ensure search-bar does not pin on mobile +@media #{$bp-below-tablet} { + form#search-bar { + position: static; + } +} //Styles to override the styles from _forms.scss #search{ padding-right: 0px; diff --git a/_sass/layouts/_main.scss b/_sass/layouts/_main.scss index 78055611ab..ddca13f948 100644 --- a/_sass/layouts/_main.scss +++ b/_sass/layouts/_main.scss @@ -36,4 +36,4 @@ // This is to provide padding for readability to the content in the default-markdown.html layout #content-markdown { padding: 200px 100px 300px 100px; -} \ No newline at end of file +} diff --git a/_sass/variables/_layout.scss b/_sass/variables/_layout.scss index 9a6c6fd332..a960aaf851 100644 --- a/_sass/variables/_layout.scss +++ b/_sass/variables/_layout.scss @@ -4,6 +4,7 @@ * These are the most commonly used breakpoints for different device widths. */ $screen-desktop-large: 1632px; +$screen-desktop-medium: 1024px; $screen-desktop: 960px; $screen-tablet: 768px; $screen-mobile: 480px; @@ -18,6 +19,8 @@ $screen-mobile: 480px; */ $bp-desktop-large-up: '(min-width: #{$screen-desktop-large})'; $bp-below-desktop-large: '(max-width: #{$screen-desktop-large - .02})'; +$bp-desktop-medium-up: '(min-width: #{$screen-desktop-medium})'; +$bp-below-desktop-medium: '(max-width: #{$screen-desktop-medium - .02})'; $bp-desktop-up: '(min-width: #{$screen-desktop})'; $bp-below-desktop: '(max-width: #{$screen-desktop - .02})'; $bp-tablet-up: '(min-width: #{$screen-tablet})'; diff --git a/assets/images/sponsors/code-for-america.svg b/assets/images/former-sponsors-partners/code-for-america.svg similarity index 100% rename from assets/images/sponsors/code-for-america.svg rename to assets/images/former-sponsors-partners/code-for-america.svg diff --git a/assets/images/partners/atwater-village.png b/assets/images/partners/atwater-village.png new file mode 100644 index 0000000000000000000000000000000000000000..780edd16580cb17da0d4ce4b34388f775c563e50 GIT binary patch literal 27068 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 literal 0 HcmV?d00001 diff --git a/assets/images/technologies-icons/github-icon-1.svg b/assets/images/technologies-icons/github-icon-1.svg deleted file mode 100644 index 18e9450e01..0000000000 --- a/assets/images/technologies-icons/github-icon-1.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/assets/js/api-actionnetwork.js b/assets/js/api-actionnetwork.js deleted file mode 100644 index 754a4fc5ea..0000000000 --- a/assets/js/api-actionnetwork.js +++ /dev/null @@ -1,117 +0,0 @@ -(function (window, document, undefined) { - //capture all DOM Elements - var heroForm = document.querySelector(".hero-signup"); - var heroFormInput = document.getElementById("hero-signup"); - var heroBtn = document.getElementById("hero-signup-btn"); - - var contactForm = document.querySelector(".contact-form"); - var contactFormEmail = document.getElementById("contact-email"); - var contactMessage = document.querySelector(".contact-form textarea"); - var contactFormBtn = document.getElementById("contact-form-btn"); - - var heroFormConfirm = document.querySelector(".form-confirmation strong"); - var contactFormConfirm = document.querySelector( - ".contact-form .form-confirmation strong" - ); - - // API CONNECTION INFO - var ACTION_NETWORK_API = ""; - var url = "https://actionnetwork.org/api/v2/people/"; - - // FORM SUBMISSION HELPER FUNCTIONS - var submitEmail = function (url = ``, email) { - var postData = { - person: { - email_addresses: [{ - address: email - }] - } - }; - - return fetch(url, { - method: "POST", - headers: { - "OSDI-API-Token": ACTION_NETWORK_API, - "Content-Type": "application/json" - }, - body: JSON.stringify(postData) - }).then(response => response.json()); - }; - - var setPostMessage = function (targetNode, error) { - var successMessage = document.createTextNode( - "Thanks! You'll hear from us soon." - ); - var errorMessage = document.createTextNode(error); - - if (error) { - targetNode.innerHTML = ''; - targetNode.appendChild(errorMessage); - } else { - targetNode.innerHTML = ''; - targetNode.appendChild(successMessage); - } - }; - - var validateEmail = function (email) { - var pattern = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/ - - return pattern.test(email); - } - - // EVENT LISTENERS FOR FORM SUBMISSIONS - if (heroBtn) { - heroBtn.addEventListener("click", function (event) { - event.preventDefault(); - var email = heroFormInput.value; - - if (validateEmail(email)) { - submitEmail(url, email) - .then(function (data) { - if (data.error) { - setPostMessage(heroFormConfirm, data.error); - } else { - setPostMessage(heroFormConfirm); - } - - heroForm.reset(); - }) - .catch(function (error) { - var errorMessage = document.createTextNode(error.message); - heroFormConfirm.appendChild(errorMessage); - heroForm.reset(); - }); - } else { - setPostMessage(heroFormConfirm, "Invalid Email Format"); - } - }); - } - - if (contactFormBtn) { - contactFormBtn.addEventListener("click", function (event) { - event.preventDefault(); - var email = contactFormEmail.value; - - if (validateEmail(email)) { - submitEmail(url, email) - // submitEmail(url, email) - .then(function (data) { - if (data.error) { - setPostMessage(contactFormConfirm, data.error); - } else { - setPostMessage(contactFormConfirm); - } - - contactForm.reset(); - }) - .catch(function (error) { - var errorMessage = document.createTextNode(error.message); - contactFormConfirm.appendChild(errorMessage); - contactForm.reset(); - }); - } else { - setPostMessage(contactFormConfirm, "Invalid Email Format"); - } - }); - } -})(window, document); diff --git a/assets/js/communities-of-practice.js b/assets/js/communities-of-practice.js new file mode 100644 index 0000000000..2500c5639b --- /dev/null +++ b/assets/js/communities-of-practice.js @@ -0,0 +1,60 @@ +--- +--- + +{% assign vrmsData = site.data.external.vrms_data %} +const vrmsData = JSON.parse(decodeURIComponent("{{ vrmsData | jsonify | uri_escape }}")); + +document.addEventListener("DOMContentLoaded", function() { + // Function to retrieve and format meeting times + function getMeetingTimes(projectName) { + const project = vrmsData.find(event => + event.project && event.project.name.startsWith("Community of Practice") && event.project.name.includes(projectName) + ); + + if (project) { + // Convert to Pacific Time + const options = { timeZone: "America/Los_Angeles", hour: 'numeric', minute: 'numeric', hour12: true }; + const startTime = new Date(project.startTime); + const endTime = new Date(project.endTime); + + // Format in Pacific Time + const formatter = new Intl.DateTimeFormat('en-US', options); + const formattedStartTime = formatter.format(startTime); + const formattedEndTime = formatter.format(endTime); + + // Get the day of the week + const dayFormatter = new Intl.DateTimeFormat('en-US', { weekday: 'long', timeZone: 'America/Los_Angeles' }); + const dayOfWeek = dayFormatter.format(startTime); + + // Make it plural form for the day + const dayOfWeekPlural = dayOfWeek + 's'; + + return `${dayOfWeekPlural} ${formattedStartTime} - ${formattedEndTime} PT`; + } else { + return "TBD"; + } + } + + // sets the meeting times for each community + function setMeetingTimes() { + const communities = document.querySelectorAll('[id^="meeting-times-"]'); + + communities.forEach(element => { + const communityName = element.id.replace('meeting-times-', '').replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); + + // Map community names to their corresponding projectnames + let projectName = ""; + if (communityName === "Project/Product Management") { + projectName = "Product Management"; + } else if (communityName === "Ui/Ux") { + projectName = "UI/UX"; + } else { + projectName = communityName; + } + + element.innerHTML = getMeetingTimes(projectName); + }); + } + + setMeetingTimes(); +}); \ No newline at end of file diff --git a/assets/js/current-projects.js b/assets/js/current-projects.js index ad40fd7d5a..c6d0f3068c 100644 --- a/assets/js/current-projects.js +++ b/assets/js/current-projects.js @@ -28,7 +28,7 @@ document.addEventListener("DOMContentLoaded",function(){ if (window.location.pathname === '/projects-check/') { filterTitle = filterName; } else { - filterTitle = 'languages / technologies' + filterTitle = 'languages / technologies / tools' } filterValue.sort((a,b)=> { a = a.toLowerCase() @@ -40,7 +40,32 @@ document.addEventListener("DOMContentLoaded",function(){ } else { filterTitle = filterName; } - document.querySelector('.filter-list').insertAdjacentHTML( 'beforeend', dropDownFilterComponent( filterName,filterValue,filterTitle) ); + // for issue #4648, needed to add languages inside the technologies filter-item group, might be able to optimize for future iterations + + // This ensures that the /projects-check page does not change + if ((filterName === 'languages' || filterName === 'tools') && window.location.pathname === '/projects/') { + // remove the view all button + document.querySelector(`#technologies`).lastElementChild.remove() + // insert data inside at the end of the category + document.querySelector(`#technologies`).insertAdjacentHTML( 'beforeend', addToDropDownFilterComponents(filterName, filterValue)); + // change filterName so that the view all button will be added back + filterName = 'technologies' + // get all li elements from #technologies + liValues = Array.from(document.querySelector('#technologies').querySelectorAll('li')) + // sort the array of li elements + liValues.sort((a,b) => { + const textA = a.querySelector('label').textContent.trim() + const textB = b.querySelector('label').textContent.trim() + return textA.localeCompare(textB) + }) + // clear existing contents of #technologies + document.querySelector('#technologies').innerHTML = '' + // append sorted li + liValues.forEach(li => document.querySelector('#technologies').appendChild(li)) + } else { + document.querySelector('.filter-list').insertAdjacentHTML( 'beforeend', dropDownFilterComponent( filterName,filterValue,filterTitle) ); + } + if (document.getElementById(filterName).getElementsByTagName("li").length > 8) { document.getElementById(filterName).insertAdjacentHTML( 'beforeend', `
  • View all
  • ` ); } @@ -230,7 +255,9 @@ function createFilter(sortedProjectData){ // 'looking': [ ... new Set( (sortedProjectData.map(item => item.project.looking ? item.project.looking.map(item => item.category) : '')).flat() ) ].filter(v=>v!='').sort(), // ^ See issue #1997 for more info on why this is commented out 'programs': [...new Set(sortedProjectData.map(item => item.project.programAreas ? item.project.programAreas.map(programArea => programArea) : '').flat() ) ].filter(v=>v!='').sort(), - 'technologies': [...new Set(sortedProjectData.map(item => (item.project.technologies && item.project.languages?.length > 0) ? [item.project.languages, item.project.technologies].flat() : '').flat() ) ].filter(v=>v!='').sort(), + 'technologies': [...new Set(sortedProjectData.map(item => (item.project.technologies?.length > 0) ? [item.project.technologies].flat() : '').flat() ) ].filter(v=>v!='').sort(), + 'languages': [...new Set(sortedProjectData.map(item => (item.project.languages?.length > 0) ? [item.project.languages].flat() : '').flat())].filter(v => v != '').sort(), + 'tools': [...new Set(sortedProjectData.map(item => (item.project.tools?.length > 0) ? [item.project.tools].flat() : '').flat() ) ].filter(v=>v!='').sort(), 'status': [... new Set(sortedProjectData.map(item => item.project.status))].sort() } } @@ -281,9 +308,10 @@ function viewAllEventHandler(e) { //event handler for keyboard users to click spans when focused function tabFocusedKeyDownHandler(e) { // if user is using tab index and keys space or enter on item that needs to be clicked, it will be clicked - if ((event.key === "Enter" || event.key === "Spacebar" || event.key === " ") && document.activeElement.getAttribute("aria-label")) { + if ((e.key === "Enter" || e.key === "Spacebar" || e.key === " ") && document.activeElement.getAttribute("aria-label")) { document.activeElement.click() } + } // shows filters popup on moble function showFiltersEventHandler(e) { @@ -433,13 +461,24 @@ function updateFilterFrequency(){ function updateCategoryCounter(filterParams){ let container = [] for(const [key,value] of Object.entries(filterParams)){ - if (key !== 'Search') { - container.push([`counter_${key}`,value.length]); - } + // for issue #4648, added this modifiedKey so that the counter for languages will be tied to technologies + let modifiedKey = key + // for issue #6196 - added tools to the counter + if (key === 'languages' || key === 'tools') { + modifiedKey = 'technologies' + } + if (key !== 'Search') { + container.push([`counter_${modifiedKey}`,value.length]); + } } for(const [key,value] of container){ - document.querySelector(`#${key}`).innerHTML = ` (${value})`; + // for issue #4648, added this to show the sum of selected filters for both technology and language filters + let totalValue = 0 + for (const innerValue of container){ + totalValue += innerValue[1] + } + document.querySelector(`#${key}`).innerHTML = ` (${totalValue})`; } } @@ -455,8 +494,8 @@ function updateProjectCardDisplayState(filterParams){ if(key !=='Search'){ projectCardObj[key] = projectCard.dataset[key].split(","); } - else{ - const searchAreas=['technologies','description','partner','programs','title']; + else { + const searchAreas=['technologies','description','partner','programs','title','languages', 'tools']; for(const area of searchAreas){ projectCardObj[area]=projectCard.dataset[area].split(","); } @@ -654,12 +693,18 @@ function clearAllEventHandler(){ /** * Takes a single project object and returns the html string representing the project card */ -function projectCardComponent(project){ +function projectCardComponent(project) { + const projectLanguages = project.languages ? [... new Set(project.languages.map(lang => lang))] : "" + const projectTechnologies = project.technologies ? [... new Set(project.technologies.map(t => t))] : "" + const projectTools = project.tools ? [... new Set(project.tools.map(t => t))] : "" + // the data-technologies attr will be used by UpdateFilterFrequency + // to generate Filter's Object + const dataTechnologiesArr = [...projectLanguages, ...projectTechnologies, ...projectTools] return `
  • + ` +
  • + + +
  • + ` + ).join("")} + ` +} + /** * Takes a name of a checkbox filter and the value of the check boxed filter * and creates a html string representing a button diff --git a/assets/js/elements/noResultsMessageFilter.js b/assets/js/elements/noResultsMessageFilter.js index 2b0007c38a..36e2b9f289 100644 --- a/assets/js/elements/noResultsMessageFilter.js +++ b/assets/js/elements/noResultsMessageFilter.js @@ -1,12 +1,13 @@ function noResultsMessageComponent(filterParams, textColor) { - let filterList = `` - for (let key in filterParams) { - if (filterParams[key].length) { - for (let i = 0; i < filterParams[key].length; i++) { - filterList += `

    "${key}: ${filterParams[key][i]}"

    ` - } - } - } + let filterList = `` + let filterNameSingular = {"technologies": "Technology", "languages": "Language", "tools": "Tool", "programs": "Program", "status": "Status", "Search": "Search"} + for (let key in filterParams) { + if (filterParams[key].length) { + for (let i = 0; i < filterParams[key].length; i++) { + filterList += `

    "${filterNameSingular[key]}: ${filterParams[key][i]}"

    ` + } + } + } const noResultsMsgEle = document.querySelector(".no-results-message") noResultsMsgEle.style.color = textColor diff --git a/assets/js/events-check.js b/assets/js/events-check.js new file mode 100644 index 0000000000..c96648fdff --- /dev/null +++ b/assets/js/events-check.js @@ -0,0 +1,45 @@ +const locationsDropDown = document.querySelector(".getting-started-mobile-page"); +const showingLocations = document.querySelector(".mobile-locations-dropdown"); +const showContent = document.querySelectorAll(".event-title"); +const showLocations = document.querySelector(".event-title-1"); + +showLocations.addEventListener("click", function () { + this.classList.toggle("active"); + if (showingLocations.style.display == "block") { + showingLocations.style.display = "none"; + } else { + showingLocations.style.display = "block"; + } +}); + +for (let i = 0; i < showContent.length; i++) { + showContent[i].addEventListener("click", showingDropDown); +} + +function showingDropDown() { + if(document.body.clientWidth<767){ + this.classList.toggle("active"); + let dropDown = this.nextElementSibling; + if (dropDown.style.display === "block") { + dropDown.style.display = "none"; + } else { + dropDown.style.display = "block"; + } + } +} +document.querySelector('.flex-page-card').addEventListener('resize',handleScreenResize) +function handleScreenResize(){ + if(document.body.clientWidth>767){ + const columns = document.querySelectorAll('.mobile-dropdown'); + for(let column of columns){ + column.style.display='block'; + column.previousElementSibling.classList.remove('active'); + } + } + else{ + const columns = document.querySelectorAll('.mobile-dropdown'); + for(let column of columns){ + column.style.display='none'; + } +} +} \ No newline at end of file diff --git a/assets/js/events.js b/assets/js/events.js index 12f65f6880..40617c054c 100644 --- a/assets/js/events.js +++ b/assets/js/events.js @@ -27,18 +27,27 @@ } } } - document.querySelector('.flex-page-card').addEventListener('resize',handleScreenResize) - function handleScreenResize(){ - if(document.body.clientWidth>767){ - const columns = document.querySelectorAll('.mobile-dropdown'); - for(let column of columns){ + window.addEventListener('resize', handleScreenResize); + + /** + * Handles the screen resize event for event cards + * When the screen width is greater than 767 pixels (tablet/desktop), disables mobile dropdown, removes the arrow and display card content + * When the screen width is less than or equal to 767 pixels (mobile), enables cards mobile dropdown and fold the cards, unless already unfolded ('active'). + */ + function handleScreenResize() { + const columns = document.querySelectorAll('.mobile-dropdown'); + + if (document.body.clientWidth > 767) { + for(let column of columns) { column.style.display='block'; column.previousElementSibling.classList.remove('active'); } - } - else{ - const columns = document.querySelectorAll('.mobile-dropdown'); - for(let column of columns){ + } else { + for (let column of columns) { + if (column.previousElementSibling.classList.contains('active')) { + // when collapsing cards, skip the ones unfolded manually + continue; + } column.style.display='none'; } } diff --git a/assets/js/project-meetings.js b/assets/js/project-meetings.js index 8e01c69f7d..5ee5f632f9 100644 --- a/assets/js/project-meetings.js +++ b/assets/js/project-meetings.js @@ -6,11 +6,18 @@ import { getEventData, insertEventSchedule } from "./utility/api-events.js"; (async function main() { const eventData = await getEventData(); - //Displays/Inserts event schedule to DOM - document.addEventListener( + // If the document is still loading, add an EventListener. There is no race conditiion because JavaScript has run-to-completion semantics + if (document.readyState === "loading") + { + document.addEventListener( "DOMContentLoaded", - insertEventSchedule(eventData, "project-meetings") - ); + function(){insertEventSchedule(eventData, "project-meetings")} + ); + } + + // If the document is not in the loading state, the DOM content has loaded and the event schedule can be populated + else {insertEventSchedule(eventData, "project-meetings")} + //Displays/Inserts the user's time zone in the DOM document .querySelector("#userTimeZone") diff --git a/assets/js/project.js b/assets/js/project.js index faf755d123..1a375d2995 100644 --- a/assets/js/project.js +++ b/assets/js/project.js @@ -1,13 +1,14 @@ --- --- - /* - Fetch the correct project +Fetch the correct project */ {% assign projects = site.data.external.github-data %} // Escapes JSON for injections. See: #2134. If this is no longer the case, perform necessary edits, and remove this comment. let projects = JSON.parse(decodeURIComponent("{{ projects | jsonify | uri_escape }}")); +import { vrmsDataFetch, localeTimeIn12Format } from './utility/vrms-events.js'; + /* Passing script attributes from html script tag to JS file https://www.gun.io/blog/pass-arguments-to-embedded-javascript-tutorial-example @@ -18,6 +19,7 @@ const project = findProjectById(projectId); function findProjectById(identification){ // Starts at 1 now since the first element is a time stamp + for (let i = 1; i < projects.length; i++){ let itemId = projects[i].id.toString(); if(itemId == identification){ @@ -135,101 +137,35 @@ let meetingsHeader = document.querySelector('.meetingsHeader'); let projectTitle = scriptTag.getAttribute("projectTitle"); let meetingsFound = []; -// Grab the meeting time data from the vrms_data.json file -{% assign vrmsData = site.data.external.vrms_data %} -// Escapes JSON for injections. See: #2134. If this is no longer the case, perform necessary edits, and remove this comment. -const vrmsData = JSON.parse(decodeURIComponent("{{ vrmsData | jsonify | uri_escape }}")); - -// Helper function to sort VRMS data by day of the week from "date" key and meeting time from "startTime" key -function sortByDate(scheduleData) { - const map = { - 'Mon': 1, - 'Tue': 2, - 'Wed': 3, - 'Thu': 4, - 'Fri': 5, - 'Sat': 6, - 'Sun': 7 - }; - - scheduleData.sort(function(a, b) { - const day1 = new Date(a.date).toString().substring(0, 3); - const day2 = new Date(b.date).toString().substring(0, 3); - - return map[day1] - map[day2]; - }); - - scheduleData.sort(function(a, b) { - const day1 = new Date(a.date).toString().substring(0, 3); - const day2 = new Date(b.date).toString().substring(0, 3); - const time1 = new Date(a.startTime).toString().substring(16, 21); - const time2 = new Date(b.startTime).toString().substring(16, 21); - - if (day1 === day2) { - if (time1 > time2) { - return 1; - } else { - return -1; - } - } else { - return 1; - } - }); -} - // Loops through the VRMS data and inserts each meeting time into the HTML of the correct project page function appendMeetingTimes(scheduleData) { - - sortByDate(scheduleData); - for (const event of scheduleData) { try { - const startTime = timeFormat(new Date(event.startTime)); - const endTime = timeFormat(new Date(event.endTime)); + const startTime = localeTimeIn12Format(event.startTime); + const endTime = localeTimeIn12Format(event.endTime); const projectName = event.project.name; const name = event.name; const day = new Date(event.date).toString().substring(0,3); + + // for adding a meeting description if it exists + const meetingDescription = event.description; + // only append the meeting times to the correct project page if (projectTitle.toLowerCase() === projectName.toLowerCase()) { - meetingsList.insertAdjacentHTML("beforeend", `
  • ${day} ${startTime} - ${endTime}
    ${name}
  • `); + // added description with
    ${meetingDescription} + meetingsList.insertAdjacentHTML("beforeend", `
  • ${day} ${startTime} - ${endTime}
    ${name}
    ${meetingDescription}
  • `); meetingsFound.push(day); } - } catch (e) { console.error(e); } } } -appendMeetingTimes(vrmsData); - +vrmsDataFetch("project", appendMeetingTimes) if (meetingsFound.length >= 1) { meetingsHeader.insertAdjacentHTML("beforeend", 'Meetings'); document.querySelector('#userTimeZone').insertAdjacentHTML('afterbegin', timeZoneText()); -} - -// Formats time to be readable -function timeFormat(time) { - let hours = time.getHours(); - let minutes = time.getMinutes(); - - if (minutes == 0) { - minutes = minutes + "0"; - } - - if (hours < 12) { - return `${hours}:${minutes} am`; - } - else if (hours > 12){ - hours = hours - 12; - return `${hours}:${minutes} pm`; - } - else if (hours = 12){ - return `${hours}:${minutes} pm`; - } else { - return `${hours}:${minutes} am`; - } - } \ No newline at end of file diff --git a/assets/js/right-col-content-check.js b/assets/js/right-col-content-check.js new file mode 100644 index 0000000000..372d790167 --- /dev/null +++ b/assets/js/right-col-content-check.js @@ -0,0 +1,25 @@ +import { getEventData, insertEventSchedule } from "./utility/api-events.js"; + +/** + * This type of function is called an IIFE function. The main function is the primarily controller that loads the recurring events on this page. + * Refer: https://developer.mozilla.org/en-US/docs/Glossary/IIFE + */ +(async function main() { + const eventData = await getEventData(); + + //Displays/Inserts event schedule to DOM + if (document.readyState === "loading") { + document.addEventListener( + "DOMContentLoaded", + () => { insertEventSchedule(eventData, "events"); } + ); + } + else { + insertEventSchedule(eventData, "events"); + } + + //Displays/Inserts the user's time zone in the DOM + document + .querySelector("#userTimeZone") + .insertAdjacentHTML("afterbegin", timeZoneText()); +})(); \ No newline at end of file diff --git a/assets/js/right-col-content.js b/assets/js/right-col-content.js index 7571c60999..b62362135a 100644 --- a/assets/js/right-col-content.js +++ b/assets/js/right-col-content.js @@ -1,19 +1,124 @@ -import { getEventData, insertEventSchedule } from "./utility/api-events.js"; - +import { vrmsDataFetch, localeTimeIn12Format } from "./utility/vrms-events.js" /** * This type of function is called an IIFE function. The main function is the primarily controller that loads the recurring events on this page. * Refer: https://developer.mozilla.org/en-US/docs/Glossary/IIFE */ -(async function main() { - const eventData = await getEventData(); +(function main() { + const eventData = vrmsDataFetch("events") //Displays/Inserts event schedule to DOM - document.addEventListener( - "DOMContentLoaded", - insertEventSchedule(eventData, "events") - ); + if (document.readyState === "loading") { + document.addEventListener( + "DOMContentLoaded", + () => { insertEventSchedule(eventData, "events"); } + ); + } + else { + insertEventSchedule(eventData, "events"); + } + //Displays/Inserts the user's time zone in the DOM document .querySelector("#userTimeZone") .insertAdjacentHTML("afterbegin", timeZoneText()); })(); + +/** + * Inserts the recurring events into the html + * @param {Object} eventData - An array objects of the type returned by displayObject() + * @param {String} page - page that is using eventData ("events" or "project-meetings") + */ +function insertEventSchedule(eventData, page) { + + const formatedEvents = formatEventData(eventData) + + for (const [key, value] of Object.entries(formatedEvents)) { + let placeToInsert = document.querySelector(`#${key}-List`); + placeToInsert.innerHTML = ""; + // check if the day has any events + if (!value.length) { + placeToInsert.insertAdjacentHTML( + "beforeend", + `
  • There are no meetings scheduled.
  • ` + ); + } else { + value.forEach((event) => { + if (event) { + // If a project doesn't have an hflaWebsiteUrl, redirect to the project's Github page + if (event.hflaWebsiteUrl == "") { + event.hflaWebsiteUrl = event.githubUrl + } + let eventHtml; + // insert the correct html for the current page + if (page === "events") { + eventHtml = `
  • ${event.start} - ${event.end}
  • ${event.name} ${event.meetingName}${event.dsc.length > 0 ? "*" : ""}
  • `; + } else { + if(event.dsc != "") event.meetingName += ", "; + eventHtml = `
  • ${event.start} - ${event.end} ${event.name} ${event.meetingName} ${event.dsc}
  • `; + } + placeToInsert.insertAdjacentHTML("beforeend", eventHtml); + } + }); + } + } + } + + /** + * Formats event data + * @param {Object} data - array of event objects + * @return {Object} filtered and sorted data + */ + function formatEventData(data) { + const filteredData = filterVrmsData(data); + return filteredData + + } + + /** + * Filters out the needed data from the vrmsData returned from vrmsDataFetch + */ + function filterVrmsData(responseData) { + const return_obj = { + Monday: [], + Tuesday: [], + Wednesday: [], + Thursday: [], + Friday: [], + Saturday: [], + Sunday: [], + }; + responseData.forEach((item) => { + let day_of_week = getDayString(item.date); + return_obj[day_of_week].push(display_object(item)); + }); + return return_obj; + } + + /** + * @param {Date} date - A valid javscript time string. Example: "2020-05-13T02:00:00.000Z" + * @return {String} - The name of the day represented by the time string. Example 2020-05-13 was a wednesday. I.e rv = 'Wednesday' + */ + function getDayString(date) { + let new_date = new Date(date); + let options = { weekday: "long" }; + return new Intl.DateTimeFormat("en-US", options).format(new_date); + } + + /** + * Function that represent the individual object extracted from the api + */ + function display_object(item) { + if (item?.project?.name !== "Hack4LA" && !/^Test\b/i.test(item?.project?.name)) { + const rv_object = { + meetingName: item.name, + name: item.project.name, + dsc: item.description, + start: localeTimeIn12Format(item.startTime), + end: localeTimeIn12Format(item.endTime), + hflaWebsiteUrl: item.project.hflaWebsiteUrl, + githubUrl: item.project.githubUrl, + }; + return rv_object; + } + } + \ No newline at end of file diff --git a/assets/js/utility/api-events.js b/assets/js/utility/api-events.js index 09398dabff..2cf765f297 100644 --- a/assets/js/utility/api-events.js +++ b/assets/js/utility/api-events.js @@ -86,11 +86,11 @@ function filterDataFromApi(responseData) { * Sorts Filtered Date from the api end point by their start time */ function sortData(filteredData) { - for (const [key, value] of Object.entries(filteredData)) { - value.sort(function (a, b) { + Object.values(filteredData).forEach(value => { + value.sort((a, b) => { return convertTime12to24(a.start) - convertTime12to24(b.start) || a.name.localeCompare(b.name); }); - } + }); return filteredData; } @@ -118,7 +118,6 @@ function localeTimeIn12Format(time) { */ function getDayString(date) { let new_date = new Date(date); - let weekday = new_date.getDay(); let options = { weekday: "long" }; return new Intl.DateTimeFormat("en-US", options).format(new_date); } @@ -161,4 +160,4 @@ function display_object(item) { } } -export { getEventData, insertEventSchedule }; +export { getEventData, insertEventSchedule }; \ No newline at end of file diff --git a/assets/js/utility/vrms-events.js b/assets/js/utility/vrms-events.js new file mode 100644 index 0000000000..7eb2ec20cd --- /dev/null +++ b/assets/js/utility/vrms-events.js @@ -0,0 +1,79 @@ +--- +--- + +{% assign vrmsData = site.data.external.vrms_data %} +const vrmsData = JSON.parse(decodeURIComponent("{{ vrmsData | jsonify | uri_escape }}")); + +/* vrmsDataFilter is a function that filters the vrmsData array to remove the instances of "test" or "testing" from the events page. +We need to add logic for removing any event that contain "test" or "testing" (case-insensitive) from the events page. +*/ +const vrmsDataFilter = (vrmsData) => vrmsData.filter(data => data.name.match(/\btest(ing)?\b/i) === null); +const filteredVrmsData = vrmsDataFilter(vrmsData); + +/* vrmsDataFetch calls sortByDate function and passes filteredVrmsData variable, current page which can either be "events" for the right-col-content.html page or +"project" from the project.html page, and passes the appendMeetingTimes function from projects.js that appends the sorted vrmsData +returned by sortByDate to project.html. AppendMeetingTimes is only called if vrmsDataFetch is being called from project.js for the project.html page +*/ +export const vrmsDataFetch = (currentPage, appendMeetingTimes) => { + return sortByDate(filteredVrmsData, currentPage, appendMeetingTimes) +} + + // Helper function used for project.html and right-col-content.html to sort VRMS data by day of the week from "date" key and meeting time from "startTime" key + function sortByDate(scheduleData, currentPage, appendMeetingTimes) { + const map = { + 'Mon': 1, + 'Tue': 2, + 'Wed': 3, + 'Thu': 4, + 'Fri': 5, + 'Sat': 6, + 'Sun': 7 + }; + + scheduleData.sort(function(a, b) { + const day1 = new Date(a.date).toString().substring(0, 3); + const day2 = new Date(b.date).toString().substring(0, 3); + + return map[day1] - map[day2]; + }); + + scheduleData.sort(function(a, b) { + const day1 = new Date(a.date).toString().substring(0, 3); + const day2 = new Date(b.date).toString().substring(0, 3); + const time1 = new Date(a.startTime).toString().substring(16, 21); + const time2 = new Date(b.startTime).toString().substring(16, 21); + + if (day1 === day2) { + if (time1 > time2) { + return 1; + } else { + return -1; + } + } else { + return 1; + } + }); + + if (currentPage === "events") return scheduleData + else if (currentPage === "project") appendMeetingTimes(scheduleData) +} + +/** + * @param {Date} time - A valid javscript time string. Example: "2020-05-13T02:00:00.000Z" + * @return {String} - A time string formatted in the 12 hour format and converted to your timezone. Example: "10:00 pm" +*/ +// Formats time to be readable for projects.html and right-col-content.html page +export function localeTimeIn12Format(time) { + return new Date(time) + .toLocaleTimeString( + {}, + { + timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, + hour12: true, + hour: "numeric", + minute: "numeric", + } + ) + .toLowerCase(); + } + diff --git a/assets/js/wins.js b/assets/js/wins.js index 52ca85d7d1..540f80302e 100644 --- a/assets/js/wins.js +++ b/assets/js/wins.js @@ -236,8 +236,8 @@ if (document.querySelectorAll('.wins-card').length == 0) { const page = document.querySelector('.wins-page-contain'); const p = document.createElement('p'); + p.textContent = "No one has shared a win yet...be the first!"; page.appendChild(p); - p.innerHTML = "No one has shared a win yet...be the first!"; } } @@ -331,13 +331,31 @@ if (card[github_url].length > 0){ cloneCardTemplate.querySelector('.wins-card-github-icon').href = card[github_url]; cloneCardTemplate.querySelector('.github-icon').src = GITHUB_ICON ; - cloneCardTemplate.querySelector('.github-icon').alt = `Github profile for ${card[name]}`; + cloneCardTemplate.querySelector('.github-icon').alt = `GitHub profile for ${card[name]}`; } else { cloneCardTemplate.querySelector('.wins-card-github-icon').setAttribute('hidden', 'true') } - cloneCardTemplate.querySelector('.project-inner.wins-card-team').innerHTML = `Team(s): ${card[team]}`; - cloneCardTemplate.querySelector('.project-inner.wins-card-role').innerHTML = `Role(s): ${card[role]}`; + // Avoiding using innerHTML due to security risks + // Creating the elements + const teamContainer = cloneCardTemplate.querySelector('.project-inner.wins-card-team'); + const roleContainer = cloneCardTemplate.querySelector('.project-inner.wins-card-role'); + const teamSpanElement = document.createElement('span'); + teamSpanElement.classList.add('wins-team-role-color'); + const roleSpanElement = document.createElement('span'); + roleSpanElement.classList.add('wins-team-role-color'); + + // Preparing the text of the elements + teamSpanElement.textContent = "Team(s): "; + const teamTextNode = document.createTextNode(card[team]); + roleSpanElement.textContent = "Role(s): "; + const roleTextNode = document.createTextNode(card[role]); + + // Inserting the elements into the DOM + teamContainer.appendChild(teamSpanElement); + teamContainer.appendChild(teamTextNode); + roleContainer.appendChild(roleSpanElement); + roleContainer.appendChild(roleTextNode); cloneCardTemplate.querySelector('.wins-card-overview').textContent = card[overview]; cloneCardTemplate.querySelector('.wins-icon-container').setAttribute('data-index', index) @@ -419,13 +437,13 @@ function changeSeeMoreBtn(x) { const span = document.querySelectorAll(".see-more-div"); if (x.matches) { for(let i = 0; i < span.length; i++) { - span[i].innerHTML = '' + span[i].textContent = '' } } else { for(let i = 0; i < span.length; i++) { // removes show-less-btn class span[i].setAttribute('class', 'see-more-div'); - span[i].innerHTML = "See More"; + span[i].textContent = "See More"; } } } @@ -483,7 +501,7 @@ function changeSeeMoreBtn(x) { bigQuoteImg.alt = "Quote from " + data[i][name]; const overlayIcons = document.querySelector('#overlay-icons'); - overlayIcons.innerHTML = ""; + overlayIcons.textContent = ""; if (data[i][linkedin_url].length > 0) { makeIcon(data[i][linkedin_url], overlayIcons, 'linkedin-icon', '/assets/images/wins-page/icon-linkedin-small.svg', 'LinkedIn profile for ' + data[i][name]); @@ -492,16 +510,16 @@ function changeSeeMoreBtn(x) { } const overlayName = document.querySelector('#overlay-name'); - overlayName.innerHTML = data[i][name]; + overlayName.textContent = data[i][name]; const overlayTeams = document.querySelector('#overlay-teams'); - overlayTeams.innerHTML = `Team(s): ${data[i][team]}`; + overlayTeams.textContent = `Team(s): ${data[i][team]}`; const overlayRoles = document.querySelector('#overlay-roles'); - overlayRoles.innerHTML = `Role(s): ${data[i][role]}`; + overlayRoles.textContent = `Role(s): ${data[i][role]}`; const overlayOverview = document.querySelector('#overlay-overview'); - overlayOverview.innerHTML = data[i][overview]; + overlayOverview.textContent = data[i][overview]; insertIcons('#overlay-info', data[i][win], 'overlay') @@ -524,7 +542,7 @@ function changeSeeMoreBtn(x) { const overlayInfo = document.querySelector('#overlay-info'); - overlayInfo.innerHTML = ''; + overlayInfo.textContent = ''; } diff --git a/assets/pdfs/Expunge-Assist-One-Sheet.pdf b/assets/pdfs/Expunge-Assist-One-Sheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..40d57aa5b598a5d6d877e5ee4c7b5c420816157b GIT binary patch literal 69033 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 zÐ+#oEVd~ld!>q6KAtxZ;?&)JLomWt=mVV3Rrg9rbb*e!1RtagLvRttGccB|p* zs!OEn1i=i_Hpp>M|CZSPzK+9SC@3jNo29`PmaMiRQ}ZB7+fULnL14qh?&VJ}=j-Rg3ICOLdM_BStA2H~ zA;Kt3jaU1@dC8^GxbP0Ip2WL2H_&V)qc-(3hSY{V$?jQB7ryGhg|xA@gr|O z3fKpTbNF18FQgy9Xli`HYgcd$MRQ|5n;9=-+GlfFxYaQ9xsQz=v_&H%GxHQAamGmC z59i@~dOKqlfsQSkQ?PVfP8iD>>booJGjn{c9?f^`==GNHd8q<+$%o_S%Ghy7b|LkA zIagiBXVhB~=BI@t=g^Ld)%NMb=*!e-E7|6LX@`21AIe(YwP3msMsVG_6;VIoR&VDh2cB2smPgehcXZ#C^T<$`O6$%MP z#+RLF-L{H*OKq0{@^HO5?Io?Y1Bt?XK=XVBiaIo5i^J68jQ&NkHlKsZ7~SX)y%Y_B zVT<{O_Hj>_ho&#t`^LFQkP{H>k-IcZwLjvJp7+#8JzYz_*@}jd&@W;a`bpa3yplZR za7iCI?rxS2%p97Zz#GA}`7CEKOwMj79dezd-pkw&oG5(ZuQ92IiGFWE^-4y#;sa zA?SXy*$F_O%|tm@@Uf@OrVY-WJrl?3d^zB>cSl$3t0Zi^Ak0r_tRnN-mnPh(`G z@EjRmSqO%ZT5@n`(H0L&)%x{lD`}k&u3)@uh89KcbDyA;+TI#E7%Qhdf2()~pM$lD zyTTn9$FE)gx~vd%q-mG$@1uFGc&z%WT;i1*V>XSO%wC|YgcbFu;IBPgf{BpH4DnSg z9UCPZjT)}M8HDsu$8Lrz7<;L!K%#H5*4UCyVDp~S1}_9j$~Nz)g` z!w@@BS!~9j%$D1&W(rMC)32MZ>!X_c1l0l@Ba9s(eM)t^8T^=Q?#>RN7AI{`%VU+b zYtIHoSf~El;G9a<8w`TU!rOl%HOzldMgNCVmf+u{tpCqQ7Rx(__0B5+IsV@xS!^r} ztgP?2(>s#I%)-FV#QyFq{Ts=8=eamoIe{Gifn+iN0p9!_!1=!sdHx`D{)S}zt4aO? z$@=Gp|4I0~(^r2a|NrJ=F}-tGtW26j000qyndmPf3h<6d{iRL)75^*t=iGZTClNEp z-yA7s&c7vV{>$9@yRr2rmGzgk^*4j-FPw_~Py6bxj6Z9A-w}VOtNvoT{wn)d{vT!k zivP7Pf2->+_3NGQdS}!Aw6KWS0q?ng{|x-w*8MI1R|fO{d>PT7bDBi#e>BRU3;tZ+ z|K)f69S8fD-}OIM*ZX4j|7~@e?}FUlD6{vSz`^{t3f}QDCKe*~cWLQeF9UJ{{w;d3 zGW}ijVtsFxe;=v;PhQhMMKAdw%Pyi%Ems(LQ$qT`9SLF#sBO>(0(li134e5PiIf03 zM?1W z5^(?`hLWr?8a=g{K{=5mIHQ;!l}F(VvB;Q)Fmsps&OT_P5#h%`Htog@0ezy%o_pgK zS|3{=v>8OC_75>!MV(i$I-5+E|L!dRwg>(=^+zDy_fxua!gEYOz-~Uf5tdi-utY7#F&_Y z?~LJplmjp^v;DJP04sp~pY;ORSpPRMc9!?E*?)c?8z hardLabels.includes(label); + const isHardLabel = (label) => hardLabels.includes(label); // checks if label is a soft label - const isSoftLabel = label => softLabels.includes(label); + const isSoftLabel = (label) => softLabels.includes(label); // checks if label is an override label - const isOverrideLabel = label => overrideSoftLabels.includes(label); + const isOverrideLabel = (label) => overrideSoftLabels.includes(label); - /** If issue includes hard labels there should be no visual changes - move to the Done column */ + /** If issue includes hard labels there should be no visual changes - move to the Done status */ if (issueLabels.some(isHardLabel)) { - return doneColumn; + console.log("Found hard label- sort to 'Done' status."); + return doneStatus; } - /** if issue does not include a hard label, but does contain an override label - move to QA */ + /** if issue does not include a hard label, but does contain an override label - move to QA status */ if (issueLabels.some(isOverrideLabel)) { - return QAColumn; + console.log("Found override label- sort to 'QA' status."); + return QAStatus; } - /** if issue includes soft labels (no hard or override) - move to Done */ + /** if issue includes soft labels (no hard or override) - move to Done status */ if (issueLabels.some(isSoftLabel)) { - return doneColumn; + console.log("Found soft label- sort to 'Done' status."); + return doneStatus; } - // all other issues go to QA column - return QAColumn; + // all other issues go to QA status + console.log("Didn't find hard or soft label- sort to 'QA' status."); + return QAStatus; } module.exports = main; diff --git a/github-actions/pr-instructions/create-instruction.js b/github-actions/pr-instructions/create-instruction.js index bf650ae70d..7d936696c4 100644 --- a/github-actions/pr-instructions/create-instruction.js +++ b/github-actions/pr-instructions/create-instruction.js @@ -9,10 +9,16 @@ const fs = require('fs'); * @param {Object} c - context object * @returns {string} string containing commandline instructions, URI encoded since the backtick character causes a problem in * the artifact */ -function main({ g, c }) { +async function main({ g, c }) { github = g; context = c; - return encodeURI(compositeInstruction()); + return encodeURI(await compositeInstruction()); +} + +function formatHeaderInstruction() { + const path = './github-actions/pr-instructions/pr-instructions-header.md' + const headerInstruction = fs.readFileSync(path).toString('utf-8') + return headerInstruction } function formatPullComment(instruction) { @@ -23,7 +29,7 @@ function formatPullComment(instruction) { } function formatContribComment(instruction){ - const path = './github-actions/pr-instructions/pr-instructions-contrib-template.md' + const path = './github-actions/pr-instructions/pr-instructions-contrib-template.md' const text = fs.readFileSync(path).toString('utf-8'); const completedInstructions = text.replace('${previewContribInstructions}', instruction); return completedInstructions; @@ -41,16 +47,48 @@ git pull ${cloneURL} ${nameOfFromBranch}` } function createContribInstruction(){ - const nameOfCollaborator = context.payload.pull_request.head.repo.owner.login; + const nameOfCollaborator = context.payload.pull_request.head.repo.owner.login; const nameOfFromBranch = context.payload.pull_request.head.ref; - const previewContribURL = `https://github.com/${nameOfCollaborator}/website/blob/${nameOfFromBranch}/CONTRIBUTING.md` - return previewContribURL; + const previewContribURL = `https://github.com/${nameOfCollaborator}/website/blob/${nameOfFromBranch}/CONTRIBUTING.md` + return previewContribURL; +} + +async function getModifiedFiles() { + const prNumber = context.payload.pull_request.number; + const repoName = context.payload.pull_request.base.repo.name; + const ownerName = context.payload.pull_request.base.repo.owner.login; + + // Gets the list of files modified in the pull request and destructures the data object into a files variable + const { data: files } = await github.rest.pulls.listFiles({ + owner: ownerName, + repo: repoName, + pull_number: prNumber + }); + // Maps the files array to only include the filename of each file + const modifiedFiles = files.map(file => file.filename); + + return modifiedFiles; } -function compositeInstruction() { - const completedPullInstruction = formatPullComment(createPullInstruction()); - const completedContribInstruction = formatContribComment(createContribInstruction()); - return completedPullInstruction + completedContribInstruction; +async function compositeInstruction() { + const modifiedFiles = await getModifiedFiles(); + const isContributingModified = modifiedFiles.includes('CONTRIBUTING.md'); + const isOnlyContributingModified = isContributingModified && modifiedFiles.length === 1; + + const pullRequestHeader = formatHeaderInstruction(); + let completedPullInstruction = ''; + let completedContribInstruction = ''; + + // Only includes the pull request instructions if multiple files, including CONTRIBUTING.md, are modified + if (!isOnlyContributingModified) { + completedPullInstruction = formatPullComment(createPullInstruction()); + } + // Only include the contributing instructions if the CONTRIBUTING.md file is modified + if (isContributingModified) { + completedContribInstruction = formatContribComment(createContribInstruction()); + } + + return pullRequestHeader + completedPullInstruction + completedContribInstruction; } module.exports = main \ No newline at end of file diff --git a/github-actions/pr-instructions/post-comment.js b/github-actions/pr-instructions/post-comment.js index b4327929b3..b14254c472 100644 --- a/github-actions/pr-instructions/post-comment.js +++ b/github-actions/pr-instructions/post-comment.js @@ -1,5 +1,4 @@ // Import modules -var fs = require("fs"); const postComment = require('../utils/post-issue-comment') // Global variables diff --git a/github-actions/pr-instructions/pr-instructions-contrib-template.md b/github-actions/pr-instructions/pr-instructions-contrib-template.md index 6d27dc68c9..509de68391 100644 --- a/github-actions/pr-instructions/pr-instructions-contrib-template.md +++ b/github-actions/pr-instructions/pr-instructions-contrib-template.md @@ -1,9 +1,9 @@ ------------------- +--- Note that CONTRIBUTING.md cannot previewed locally; rather it should be previewed at this URL: ``` ${previewContribInstructions} -``` +``` diff --git a/github-actions/pr-instructions/pr-instructions-header.md b/github-actions/pr-instructions/pr-instructions-header.md new file mode 100644 index 0000000000..096310c370 --- /dev/null +++ b/github-actions/pr-instructions/pr-instructions-header.md @@ -0,0 +1,3 @@ + + +Want to review this pull request? Take a look at [this documentation](https://github.com/hackforla/website/wiki/How-to-Review-Pull-Requests) for a step by step guide! diff --git a/github-actions/pr-instructions/pr-instructions-template.md b/github-actions/pr-instructions/pr-instructions-template.md index e5f7a1fa86..9e7ad154e0 100644 --- a/github-actions/pr-instructions/pr-instructions-template.md +++ b/github-actions/pr-instructions/pr-instructions-template.md @@ -1,9 +1,9 @@ -Want to review this pull request? Take a look at [this documentation](https://github.com/hackforla/website/wiki/How-to-Review-Pull-Requests) for a step by step guide! +--- From your project repository, check out a new branch and test the changes. ``` ${commandlineInstructions} -``` +``` diff --git a/github-actions/trigger-issue/add-missing-labels-to-issues/check-labels.js b/github-actions/trigger-issue/add-missing-labels-to-issues/check-labels.js index cd429f144d..5aa85adbfa 100644 --- a/github-actions/trigger-issue/add-missing-labels-to-issues/check-labels.js +++ b/github-actions/trigger-issue/add-missing-labels-to-issues/check-labels.js @@ -1,34 +1,43 @@ +// Module imports +const statusFieldIds = require('../../utils/_data/status-field-ids'); +const queryIssueInfo = require('../../utils/query-issue-info'); +const mutateIssueStatus = require('../../utils/mutate-issue-status'); + // Constant variables -const REQUIRED_LABELS = ['Complexity', 'role', 'Feature', 'size'] -const LABEL_MISSING = ['Complexity: Missing', 'role missing', 'Feature Missing', 'size: missing'] -const COMPLEXITY_EXCEPTIONS = ['good first issue'] +const REQUIRED_LABELS = ['Complexity', 'role', 'Feature', 'size']; +const LABEL_MISSING = ['Complexity: Missing', 'role missing', 'Feature Missing', 'size: missing']; +const COMPLEXITY_EXCEPTIONS = ['good first issue']; // SPECIAL_CASE is for issue created by reference with issue title "Hack for LA website bot" (from "Review Inactive Team Members") -const SPECIAL_CASE = ['ready for dev lead','Feature: Administrative','size: 0.25pt','Complexity: Small','role: dev leads'] +const SPECIAL_CASE = ['ready for dev lead','Feature: Administrative','size: 0.25pt','Complexity: Small','role: dev leads']; // Global variables -var github -var context +var github; +var context; /** * Check the labels of an issue, and add/remove labels as necessary - * @param {Object} g - github object + * @param {Object} g - GitHub object * @param {Object} c - context object * @returns - returns an object with the action's result, which is passed on to the next action */ async function main({ g, c }) { - github = g - context = c - const issueNum = context.payload.issue.number - const issueTitle = context.payload.issue.title + github = g; + context = c; + const issueNum = context.payload.issue.number; + const issueTitle = context.payload.issue.title; - const labels = obtainLabels() - const filteredLabels = filterLabels(labels) - let labelsToAdd = checkLabels(filteredLabels) + const labels = obtainLabels(); + const filteredLabels = filterLabels(labels); + let labelsToAdd = checkLabels(filteredLabels); - // for SPECIAL_CASE noted above + // Labels for SPECIAL_CASE noted above, change issue status to "Questions / In Review" if (issueTitle.includes('Hack for LA website bot')) { labelsToAdd = SPECIAL_CASE; + // Find GraphQL issue id and change status id, then change status + const { id: itemId } = await queryIssueInfo(github, context, issueNum); + const newStatusValue = statusFieldIds("Questions_In_Review"); + await mutateIssueStatus(github, context, itemId, newStatusValue); } if (labelsToAdd.length === 0) { @@ -37,12 +46,12 @@ async function main({ g, c }) { console.log('Labels to add: ', labelsToAdd); } - const result = await addLabels(labelsToAdd, filteredLabels) + const result = await addLabels(labelsToAdd, filteredLabels); return { actionResult: result, addedLabels: labelsToAdd, issueNum: issueNum - } + }; } /** @@ -50,9 +59,9 @@ async function main({ g, c }) { * @return {Array} - returns an array of all the labels */ function obtainLabels() { - const labelsObject = context.payload.issue.labels - const labels = labelsObject.map(label => label.name) - return labels + const labelsObject = context.payload.issue.labels; + const labels = labelsObject.map(label => label.name); + return labels; } /** @@ -62,34 +71,34 @@ function obtainLabels() { * @return {Array} - returns a filtered array without the extraneous labels */ function filterLabels(labels) { - return labels.filter(label => LABEL_MISSING.includes(label) === false) + return labels.filter(label => LABEL_MISSING.includes(label) === false); } /** * Check for missing labels - * @param {Array} labels - array of labels to check - * @return {Array} - returns an array of the labels to add + * @param {Array} labels - array of the labels to check + * @return {Array} labelsToAdd - array of the labels to add */ function checkLabels(labels) { - let labelsToAdd = [] + let labelsToAdd = []; REQUIRED_LABELS.forEach((requiredLabel, i) => { - const regExp = new RegExp(`\\b${requiredLabel}\\b`, 'gi') + const regExp = new RegExp(`\\b${requiredLabel}\\b`, 'gi'); const isLabelPresent = labels.some(label => { // If the label is in the complexity exceptions array, it also fulfills the complexity requirements if (COMPLEXITY_EXCEPTIONS.includes(label) && requiredLabel === 'Complexity') { - return true + return true; } - return regExp.test(label) + return regExp.test(label); }) - if (isLabelPresent === false){ - labelsToAdd.push(LABEL_MISSING[i]) + if (isLabelPresent === false) { + labelsToAdd.push(LABEL_MISSING[i]); } }) - return labelsToAdd + return labelsToAdd; } /** @@ -99,32 +108,33 @@ function checkLabels(labels) { * @return {Boolean} - boolean that states if the function succeeds */ async function addLabels(labelsToAdd, currentLabels) { - const issueNum = context.payload.issue.number - const owner = context.payload.repository.owner.login - const repo = context.payload.repository.name + const issueNum = context.payload.issue.number; + const owner = context.payload.repository.owner.login; + const repo = context.payload.repository.name; // Use a flattened set to ensure each label is unique const labels = [...new Set([ ...labelsToAdd, ...currentLabels - ])] + ])]; try { - const results = await github.rest.issues.setLabels({ + // https://octokit.github.io/rest.js/v20#issues-set-labels + await github.rest.issues.setLabels({ owner: owner, repo: repo, issue_number: issueNum, labels: labels - }) + }); if (labelsToAdd.length > 0) { - console.log('Succesfully added labels: ', labelsToAdd); + console.log(`Labels added successfully`); } - return true + return true; } catch(err) { console.log('Error editing labels: ', err) - return false + return false; } } -module.exports = main +module.exports = main; diff --git a/github-actions/trigger-issue/add-missing-labels-to-issues/post-labels-comment.js b/github-actions/trigger-issue/add-missing-labels-to-issues/post-labels-comment.js index 949f7cd8a0..6bc2811378 100644 --- a/github-actions/trigger-issue/add-missing-labels-to-issues/post-labels-comment.js +++ b/github-actions/trigger-issue/add-missing-labels-to-issues/post-labels-comment.js @@ -1,6 +1,6 @@ -var fs = require("fs") -const postComment = require('../../utils/post-issue-comment') -const formatComment = require('../../utils/format-comment') +var fs = require("fs"); +const postComment = require('../../utils/post-issue-comment'); +const formatComment = require('../../utils/format-comment'); // Constant variables const LABELS_OBJ = { @@ -8,11 +8,11 @@ const LABELS_OBJ = { 'role missing': 'Role', 'Feature Missing': 'Feature', 'size: missing': 'Size' -} +}; // Global variables -var github -var context +var github; +var context; /** * Format the label instructions into a template, then post it to the issue @@ -23,24 +23,26 @@ var context * @param {Number} issueNum - the number of the issue where the post will be made */ async function main({ g, c }, { actionResult, addedLabels, issueNum }) { - github = g - context = c + github = g; + context = c; + + const issueTitle = context.payload.issue.title; // If the previous action failed, stop here - if (actionResult === false){ + if (actionResult === false) { console.log('Previous gh-action failed. The current gh-action will end.'); - return + return; } // If addedLabels === [], no new labels are needed - if (addedLabels.length === 0) { + if (addedLabels.length === 0 || issueTitle.includes('Hack for LA website bot')) { console.log('All required labels have been included; the labels comment will not be posted.'); - return + return; } console.log('Comment will be posted to issue regarding missing labels.'); - const instructions = makeComment(addedLabels) - await postComment(issueNum, instructions, github, context) + const instructions = makeComment(addedLabels); + await postComment(issueNum, instructions, github, context); } /** @@ -49,7 +51,7 @@ async function main({ g, c }, { actionResult, addedLabels, issueNum }) { * @return {String} - returns a string of instructions to be used for the comment */ function makeComment(labels) { - const issueCreator = context.payload.issue.user.login + const issueCreator = context.payload.issue.user.login; if (labels.length === 0) { return; @@ -61,18 +63,18 @@ function makeComment(labels) { placeholderString: '${issueCreator}', filePathToFormat: './github-actions/trigger-issue/add-missing-labels-to-issues/add-labels-template.md', textToFormat: null - } - const commentWithIssueCreator = formatComment(commentObject, fs) + }; + const commentWithIssueCreator = formatComment(commentObject, fs); // Replace the labels placeholder - const labelsToAdd = labels.map(label => LABELS_OBJ[label]).join(', ') + const labelsToAdd = labels.map(label => LABELS_OBJ[label]).join(', '); const labelsCommentObject = { replacementString: labelsToAdd, placeholderString: '${labels}', filePathToFormat: null, textToFormat: commentWithIssueCreator - } - return formatComment(labelsCommentObject, fs) + }; + return formatComment(labelsCommentObject, fs); } -module.exports = main +module.exports = main; diff --git a/github-actions/trigger-issue/add-preliminary-comment/check-complexity-eligibility.js b/github-actions/trigger-issue/add-preliminary-comment/check-complexity-eligibility.js new file mode 100644 index 0000000000..7f0c19b63e --- /dev/null +++ b/github-actions/trigger-issue/add-preliminary-comment/check-complexity-eligibility.js @@ -0,0 +1,449 @@ +const fs = require('fs'); +const mutateIssueStatus = require('../../utils/mutate-issue-status'); +const postComment = require('../../utils/post-issue-comment'); +const queryIssueInfo = require('../../utils/query-issue-info'); +const statusFieldIds = require('../../utils/_data/status-field-ids'); +const { setTimeout } = require('timers/promises'); + +/** +* Checks if an assignee is eligible to be assigned an issue based on their +* previous assignments and the complexity of the current issue. +* @param {Object} github - The GitHub API client. +* @param {Object} context - The GitHub webhook event context. +* @param {boolean} isAdminOrMerge - Whether the assignee is an admin or merge team member. +* @returns {Promise} A promise that resolves to true if the assignee +* is eligible, false otherwise. +*/ + +async function checkComplexityEligibility( + github, + context, + isAdminOrMerge +) { + // If assignee is an admin or merge team member, skip complexity check + if (isAdminOrMerge) { + return true; + } + + const currentIssue = formatCurrentIssue( + context.payload.issue, + context.payload.sender + ); + + // Fetch the current issue's project item ID and status name + const { id: projectItemId, statusName } = await queryIssueInfo( + github, + context, + currentIssue.issueNum + ); + + // If issue's status is New Issue Approval, skip complexity check + if (statusName === 'New Issue Approval') { + return true; + } + + // If issue created by assignee or not self-assigned, skip complexity check + if (currentIssue.assigneeId === currentIssue.creatorId || + currentIssue.assigneeId !== currentIssue.assignerId) { + return true; + } + + const hasAnyLabel = (labels, referenceLabels) => + labels.some(label => referenceLabels.includes(label)); + + const exceptionLabels = [ + 'ER', + 'epic' + ]; + const requiredRoleLabels = [ + 'role: front end', + 'role: back end/devOps' + ]; + const requiredComplexityLabels = [ + 'good first issue', + 'Complexity: Small', + 'Complexity: Medium' + ]; + + // If issue has any exception labels, skip complexity check + if (hasAnyLabel(currentIssue.labels, exceptionLabels)) { + return true; + } + + // If issue doesn't have required labels, skip complexity check + if (!hasAnyLabel(currentIssue.labels, requiredRoleLabels) || + !hasAnyLabel(currentIssue.labels, requiredComplexityLabels)) { + return true; + } + + const assignedIssues = await fetchIssuesByAssignee( + github, + context, + currentIssue.assigneeUsername + ); + const previousIssues = assignedIssues.filter( + issue => issue.issueNum !== currentIssue.issueNum + ); + + const preWorkIssue = extractPreWorkIssueFromIssues(assignedIssues); + const assigneeRole = extractRoleFromPreWorkIssue(preWorkIssue); + + const issueComplexityPermitted = isEligibleForIssue( + currentIssue, + previousIssues, + assigneeRole + ); + + if (!issueComplexityPermitted) { + const { id: preWorkIssueProjectItemId } = + await queryIssueInfo( + github, + context, + preWorkIssue.issueNum + ); + await handleIssueComplexityNotPermitted( + github, + context, + currentIssue.issueNum, + currentIssue.assigneeUsername, + projectItemId, + preWorkIssue, + preWorkIssueProjectItemId + ); + } + + return issueComplexityPermitted; +} + +/** +* Fetches all issues assigned to a given user. +* @param {Object} github - The GitHub API client. +* @param {Object} context - The GitHub webhook event context. +* @param {string} username - The GitHub username of the assignee. +* @returns {Promise} A promise that resolves to an array of assigned +* issues. +*/ + +async function fetchIssuesByAssignee(github, context, username) { + try { + const { owner, repo } = context.repo; + const response = await github.rest.issues.listForRepo({ + owner, + repo, + assignee: username, + state: 'all', + per_page: 100, + }); + + const issues = response.data; + + if (issues.length === 0) { + return []; + } + + return issues.map(issue => ({ + issueNum: issue.number, + issueTitle: issue.title, + labels: issue.labels.map(label => label.name), + state: issue.state, + assigneeId: issue.assignee.id, + creatorId: issue.user.id, + })); + + } catch (error) { + console.error(`Error fetching issues for assignee ${username}`, error); + return []; + } +} + +// Formats the current issue data. +function formatCurrentIssue(issue, sender) { + return { + issueNum: issue.number, + issueTitle: issue.title, + labels: issue.labels.map(label => label.name), + assigneeId: issue.assignee.id, + assigneeUsername: issue.assignee.login, + assignerId: sender.id, + creatorId: issue.user.id, + }; +} + +/** +* Checks if an assignee is eligible to be assigned an issue based on their +* previous assignments and the complexity of the current issue. +* @param {Object} currentIssue - The current issue data. +* @param {Array} previousIssues - An array of previously assigned issues. +* @param {Array} assigneeRole - An array of the assignee's roles. +* @returns {boolean} True if the assignee is eligible, false otherwise. +*/ + +function isEligibleForIssue(currentIssue, previousIssues, assigneeRole) { + const currentIssueComplexityAndRoles = extractComplexityAndRolesFromLabels( + [currentIssue] + ); + const previousIssuesComplexityAndRoles = extractComplexityAndRolesFromLabels( + previousIssues + ); + + // Check good first issue eligibility + if (currentIssueComplexityAndRoles[0].complexity === 'good first issue') { + const goodFirstIssueCount = previousIssuesComplexityAndRoles.filter( + issue => issue.complexity === 'good first issue' + ).length; + + if (goodFirstIssueCount >= 2) { + return false; + } else { + return true; + } + } + + /* + Check if the assignee has only one role (front end or back end/devOps). + If so, check their eligibility for Small/Medium complexity issues + based on the number of previous issues of the same complexity. + */ + if (assigneeRole.includes('role: front end') !== + assigneeRole.includes('role: back end/devOps')) { + const complexityCount = previousIssuesComplexityAndRoles.filter( + issue => issue.complexity === currentIssueComplexityAndRoles[0].complexity + ).length; + + if (complexityCount >= 1) { + return false; + } + } + + // Check for Small/Medium complexity eligibility for assignee with both roles + let matchingComplexityIssues = []; + + if (assigneeRole.includes('role: front end') && + assigneeRole.includes('role: back end/devOps')) { + matchingComplexityIssues = previousIssuesComplexityAndRoles.filter( + issue => issue.complexity.includes( + currentIssueComplexityAndRoles[0].complexity + ) + ); + + if (matchingComplexityIssues.length >= 2) { + return false; + } + } + + /* + If there is one previous issue of the same complexity, + check the eligibility based on the role labels of the + previous and current issues. + */ + if (matchingComplexityIssues.length === 1) { + const previousMatchingIssue = matchingComplexityIssues[0]; + + const currentIssueHasFrontEnd = + currentIssueComplexityAndRoles[0].role.includes('role: front end'); + const currentIssueHasBackEnd = + currentIssueComplexityAndRoles[0].role.includes('role: back end/devOps'); + + const previousMatchingIssueHasFrontEnd = + previousMatchingIssue.role.includes('role: front end'); + const previousMatchingIssueHasBackEnd = + previousMatchingIssue.role.includes('role: back end/devOps'); + + // If the previous issue had both roles, + // the current issue must have one of the roles, but not both + if (previousMatchingIssueHasFrontEnd && previousMatchingIssueHasBackEnd) { + return (currentIssueHasFrontEnd || currentIssueHasBackEnd) && + !(currentIssueHasFrontEnd && currentIssueHasBackEnd); + + // If the previous issue had only front end role, + // the new issue must have back end role + } else if (previousMatchingIssueHasFrontEnd) { + return currentIssueHasBackEnd; + + // If the previous issue had only back end role, + // the new issue must have front end role + } else if (previousMatchingIssueHasBackEnd) { + return currentIssueHasFrontEnd; + } + } + + return true; +} + +// Extracts complexity and roles from issue labels. +function extractComplexityAndRolesFromLabels(issues) { + // Filter to only include issues not created by assignee + const filteredIssues = issues.filter( + issue => issue.assigneeId !== issue.creatorId + ); + + return filteredIssues.map(issue => ({ + complexity: issue.labels.find( + label => + label === 'good first issue' || + label === 'Complexity: Small' || + label === 'Complexity: Medium' + ), + role: issue.labels.filter( + label => + label === 'role: front end' || label === 'role: back end/devOps' + ), + })).filter(issue => issue.complexity); +} + +// Extracts the Pre-Work Checklist (Skills Issue) from assigned issues. +function extractPreWorkIssueFromIssues(assignedIssues) { + const preWorkIssue = assignedIssues.find( + issue => issue.labels.includes('Complexity: Prework') + ); + + if (!preWorkIssue) { + throw new Error( + `Assignee's Pre-Work Checklist (Skills Issue) not found in assigned issues.` + ); + } + + return preWorkIssue; +} + +// Extracts roles from the Pre-Work Checklist (Skills Issue). +function extractRoleFromPreWorkIssue(preWorkIssue) { + return preWorkIssue.labels.filter( + label => + label === 'role: front end' || label === 'role: back end/devOps' + ); +} + +/** +* Handles actions to take when an issue is not within the complexity +* eligibility for an assignee. +* @param {Object} github - The GitHub API client. +* @param {Object} context - The GitHub webhook event context. +* @param {number} currentIssueNum - The current issue number. +* @param {string} assigneeUsername - The GitHub username of the assignee. +* @param {string} currentIssueprojectItemId - The project item ID of the current +* issue. +* @param {Object} preWorkIssue - The Pre-Work Checklist (Skills Issue) object. +* @param {string} preWorkIssueProjectItemId - The project item ID of the +* Pre-Work Checklist (Skills Issue). +*/ + +async function handleIssueComplexityNotPermitted( + github, + context, + currentIssueNum, + assigneeUsername, + projectItemId, + preWorkIssue, + preWorkIssueProjectItemId +) { + try { + const { owner, repo } = context.repo; + + // Unassign assignee from the issue + await github.rest.issues.removeAssignees({ + owner, + repo, + issue_number: currentIssueNum, + assignees: [assigneeUsername], + }); + + // Add 'Ready for Prioritization' label + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: currentIssueNum, + labels: ['Ready for Prioritization'], + }); + + // Change issue's status to New Issue Approval + await mutateIssueStatus( + github, + context, + projectItemId, + statusFieldIds('New_Issue_Approval') + ); + + // If the assignee's Pre-work Checklist (Skills Issue) is closed, open it + if (preWorkIssue.state === 'closed') { + await github.rest.issues.update({ + owner, + repo, + issue_number: preWorkIssue.issueNum, + state: 'open', + }); + + // Brief delay allows Project automation to move Prework to New Issue Approval + // before script moves it to In Progress, ensuring correct final status + await setTimeout(5000); + + // Change Pre-work Checklist (Skills Issue) status to In Progress + await mutateIssueStatus( + github, + context, + preWorkIssueProjectItemId, + statusFieldIds('In_Progress') + ); + } + + const commentBody = formatComplexityReminderComment( + currentIssueNum, + assigneeUsername + ); + + // Post comment on the issue + await postComment(currentIssueNum, commentBody, github, context); + + // Post comment on the assignee's Pre-work Checklist (Skills Issue) + await postComment(preWorkIssue.issueNum, commentBody, github, context); + + } catch (error) { + throw new Error( + `Failed to handle issue complexity not permitted for issue #${currentIssueNum}: ${error.message}` + ); + } +} + +// Formats the complexity reminder comment +function formatComplexityReminderComment(issueNum, assigneeUsername) { + const replacements = [ + { + replacementString: assigneeUsername, + placeholderString: '${issueAssignee}' + }, + { + replacementString: issueNum, + placeholderString: '${issueNum}' + }, + ]; + + return formatComment( + { + replacements, + filePathToFormat: './github-actions/trigger-issue/add-preliminary-comment/developer-complexity-reminder.md', + textToFormat: null, + }, + fs + ); +} + +/** + * @description - This function formats the comment to be posted based on an array of multiple replacement objects. + * @param {Array} replacements - an array of replacement objects, each containing: + * - {String} replacementString - the string to replace the placeholder in the md file + * - {String} placeholderString - the placeholder to be replaced in the md file + * @param {String} filePathToFormat - the path of the md file to be formatted + * @param {String} textToFormat - the text to be formatted. If null, use the md file provided in the path. If provided, format that text + * @returns {String} - returns a formatted comment to be posted on github + */ +function formatComment({ replacements, filePathToFormat, textToFormat }, fs) { + let commentToPost = textToFormat === null ? fs.readFileSync(filePathToFormat).toString('utf-8') : textToFormat; + + for (const { replacementString, placeholderString } of replacements) { + commentToPost = commentToPost.replace(placeholderString, replacementString) + } + + return commentToPost; +} + +module.exports = checkComplexityEligibility; diff --git a/github-actions/trigger-issue/add-preliminary-comment/developer-complexity-reminder.md b/github-actions/trigger-issue/add-preliminary-comment/developer-complexity-reminder.md new file mode 100644 index 0000000000..8be7975412 --- /dev/null +++ b/github-actions/trigger-issue/add-preliminary-comment/developer-complexity-reminder.md @@ -0,0 +1,12 @@ + +Hello @${issueAssignee}, we appreciate you taking on issue #${issueNum}, however it looks like you've already worked on enough issues of this complexity. Try checking out some of the issues of the next complexity from the Prioritized Backlog :) + +We are going to unassign you from this issue so you can take on another issue. + +Hfla appreciates you! :) + +P.S. There is one exception to this rule/automation, and that is if you were away for a long time, and need to do the issue ladder again. If that is the case, please post the following note on the issue and on your Skills Issue (Pre-work Checklist). A Merge team member will reassign you to this issue, and will help you get assigned to subsequent issues up to medium size. + +``` +I am returning after a significant time away, and need to do the issue ladder again. Please assign me back to this issue. +``` \ No newline at end of file diff --git a/github-actions/trigger-issue/add-preliminary-comment/draft-label-reminder.md b/github-actions/trigger-issue/add-preliminary-comment/draft-label-reminder.md new file mode 100644 index 0000000000..f9a792fd12 --- /dev/null +++ b/github-actions/trigger-issue/add-preliminary-comment/draft-label-reminder.md @@ -0,0 +1,3 @@ + + +Hi @${issueAssignee}, we notice that you are assigned to an issue that you authored. Please remember to add the `Draft` label to this issue while you are working on it. \ No newline at end of file diff --git a/github-actions/trigger-issue/add-preliminary-comment/multiple-issue-reminder.md b/github-actions/trigger-issue/add-preliminary-comment/multiple-issue-reminder.md new file mode 100644 index 0000000000..f05ab4820d --- /dev/null +++ b/github-actions/trigger-issue/add-preliminary-comment/multiple-issue-reminder.md @@ -0,0 +1,6 @@ + +Hello @${issueAssignee}, we appreciate you taking on this issue, however it looks like you're already working on another issue at this time. Please wait until your current issue is merged before taking on another issue. :) + +We are going to unassign you from this issue so you can focus on your current issue. + +Hfla appreciates you! :) \ No newline at end of file diff --git a/github-actions/trigger-issue/add-preliminary-comment/preliminary-update-comment.js b/github-actions/trigger-issue/add-preliminary-comment/preliminary-update-comment.js index 66731647c4..d1160b0ce5 100644 --- a/github-actions/trigger-issue/add-preliminary-comment/preliminary-update-comment.js +++ b/github-actions/trigger-issue/add-preliminary-comment/preliminary-update-comment.js @@ -1,67 +1,245 @@ -var fs = require("fs") -const postComment = require('../../utils/post-issue-comment') -const formatComment = require('../../utils/format-comment') +// Import modules +const fs = require('fs'); +const checkComplexityEligibility = require('./check-complexity-eligibility'); +const queryIssueInfo = require('../../utils/query-issue-info'); +const mutateIssueStatus = require('../../utils/mutate-issue-status'); +const statusFieldIds = require('../../utils/_data/status-field-ids'); +const postComment = require('../../utils/post-issue-comment'); +const formatComment = require('../../utils/format-comment'); +const getTeamMembers = require('../../utils/get-team-members'); const getTimeline = require('../../utils/get-timeline'); // Global variables -var github -var context +let github; +let context; +let assignee; + +const emergentRequests = 'Emergent Requests'; +const newIssueApproval = 'New Issue Approval'; +const READY_FOR_PRIORITIZATION = "Ready for Prioritization"; + + /** - * @description - This function is the entry point into the javascript file, it formats the md file based on the result of the previous step and then posts it to the issue - * @param {Object} g - github object - * @param {Object} c - context object - * @param {Boolean} actionResult - the previous gh-action's result - * @param {Number} issueNum - the number of the issue where the post will be made + * @description This function is the entry point into the JavaScript file. It formats the + * markdown file based on the result of the previous step, checks if the developer is allowed + * to be assigned to this issue, and performs the following actions: + * - If the developer is not allowed, posts an "unassigned" comment, unassigns the developer, + * and updates the item status. + * - Posts the formatted markdown to the issue. + * @param {Object} g - GitHub object + * @param {Object} c - Context object + * @param {Boolean} shouldPost - The previous GitHub action's result + * @param {Number} issueNum - The number of the issue where the post will be made */ +async function main({ g, c }, { shouldPost, issueNum }) { + try { + // If the previous action returns false, stop here + if(shouldPost === false) { + console.log("Issue creator not a team member, no need to post comment."); + return; + } -async function main({ g, c }, { shouldPost, issueNum }){ - github = g - context = c - // If the previous action returns a false, stop here - if(shouldPost === false){ - console.log('No need to post comment.') - return - } - //Else we make the comment with the issuecreator's github handle instead of the placeholder. - else{ - const instructions = await makeComment() - if(instructions !== null){ - // the actual creation of the comment in github - await postComment(issueNum, instructions, github, context) + github = g; + context = c; + + // Get the latest developer in case there are multiple assignees + assignee = await getLatestAssignee(); + + // Check if developer is allowed to work on this issue + const isAdminOrMerge = await memberOfAdminOrMergeTeam(); + const isAssignedToAnotherIssue = await assignedToAnotherIssue(); + + // Check if developer is allowed to work on complexity level of the issue + const issueComplexityPermitted = await checkComplexityEligibility( + github, + context, + isAdminOrMerge, + ); + // If complexity not permitted, stop here, check-complexity-eligibility.js + // script will perform remaining tasks and post comment + if (issueComplexityPermitted === false) { + console.log("Issue of this complexity is not permitted."); + return; + } + + // If developer is not in Admin or Merge Teams and assigned to another issue/s, do the following: + if(!isAdminOrMerge && isAssignedToAnotherIssue) { + const comment = await createComment('multiple-issue-reminder.md', issueNum); + await postComment(issueNum, comment, github, context); + console.log(' - add `multiple-issue-reminder.md` comment to issue'); + + await unAssignDev(); + await addLabel(READY_FOR_PRIORITIZATION); + console.log(' - remove developer and add `Ready for Prioritization` label'); + + // Update item's status to "New Issue Approval" + let statusValue = statusFieldIds('New_Issue_Approval'); + const itemInfo = await queryIssueInfo(github, context, issueNum); + await mutateIssueStatus(github, context, itemInfo.id, statusValue); + console.log(' - change issue status to "New Issue Approval"'); + } else { + // Otherwise, proceed with checks + const comment = await createComment('preliminary-update.md', issueNum); + await postComment(issueNum, comment, github, context); } + } catch(error) { + throw new Error(error); } } /** - * @description - This function makes the comment with the issue assignee's github handle using the raw preliminary.md file - * @returns {string} - Comment to be posted with the issue assignee's name in it!!! + * @description - This function Check if developer is in the Admin or Merge Team + * @returns {Boolean} - return true if developer is member of Admin/Merge team, false otherwise */ +async function memberOfAdminOrMergeTeam() { + try { + // Get all members in Admin Team + const websiteAdminsMembers = await getTeamMembers(github, context, "website-admins"); + + // Get all members in Merge Team + const websiteMergeMembers = await getTeamMembers(github, context, "website-merge"); + + // Return true if developer is a member of the Admin or Merge Teams + return(assignee in websiteAdminsMembers || assignee in websiteMergeMembers); + } catch(error) { + throw new Error("Error getting membership status: " + error); + } +} + +/** + * @description - Check whether developer is assigned to another issue + * @returns {Boolean} - return true if developer is assigned to another issue/s + */ +async function assignedToAnotherIssue() { + try { + // https://octokit.github.io/rest.js/v20/#issues-list-for-repo (default state: "open") + const issues = (await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + assignee: assignee + })).data; + + const otherIssues = []; + + for(const issue of issues) { + let repoIssueNum = issue.number; + // Check is it's an "Agenda" issue + const isAgendaIssue = issue.labels.some(label => label.name === "feature: agenda"); -async function makeComment(){ - // Setting all the variables which formatComment is to be called with - var issueAssignee = context.payload.issue.assignee.login - const eventdescriptions = await getTimeline(context.payload.issue.number, github, context) - console.log(eventdescriptions.length) - //adding the code to find out the latest person assigned the issue - for(var i = eventdescriptions.length - 1 ; i>=0; i-=1){ - if(eventdescriptions[i].event == 'assigned'){ - issueAssignee = eventdescriptions[i].assignee.login - break + // Check if it's a "Prework" issue + const isPreWork = issue.labels.some(label => label.name === "Complexity: Prework"); + + // Check if it exists in "Emergent Request" Status + const inEmergentRequestStatus = (await queryIssueInfo(github, context, repoIssueNum)).statusName === emergentRequests; + + // Check if it exists in "New Issue Approval" Status + const inNewIssueApprovalStatus = (await queryIssueInfo(github, context, repoIssueNum)).statusName === newIssueApproval; + + // Include the issue only if none of the conditions are met + if(!(isAgendaIssue || isPreWork || inEmergentRequestStatus || inNewIssueApprovalStatus)) + otherIssues.push(issue); } + + // If developer is assigned to another issue/s, return true + return otherIssues.length > 1; + } catch(error) { + throw new Error("Error getting other issues: " + error); + } +} + +/** + * @description - Unassign developer from the issue + */ +async function unAssignDev() { + try { + await github.rest.issues.removeAssignees({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + assignees: [assignee], + }); + } catch(error) { + throw new Error("Error unassigning developer: " + error); } +} + +/** + * @description - Create a comment using the template + * of the filenName in "add-preliminary-comment" directory + * @param {String} fileName - the file name of the used template + * @returns {String} - return formatted comment + */ +async function createComment(fileName, issueNum) { + try { + const { statusName } = await queryIssueInfo(github, context, issueNum); + + const isPrework = context.payload.issue.labels.some((label) => label.name === 'Complexity: Prework'); + const isDraft = context.payload.issue.labels.some((label) => label.name === 'Draft'); + + if(statusName === newIssueApproval && !isDraft && !isPrework) { + if(context.payload.issue.user.login === assignee) { + fileName = 'draft-label-reminder.md'; + } else { + fileName = 'unassign-from-NIA.md'; + await unAssignDev(); + } + } + + const filePath = './github-actions/trigger-issue/add-preliminary-comment/' + fileName; + const commentObject = { + replacementString: assignee, + placeholderString: '${issueAssignee}', + filePathToFormat: filePath, + textToFormat: null + }; + // Return the formatted comment + const formattedComment = formatComment(commentObject, fs); + return formattedComment; + } catch(error) { + throw new Error("Error creating comment: " + error); + } +} - const commentObject = { - replacementString: issueAssignee, - placeholderString: '${issueAssignee}', - filePathToFormat: './github-actions/trigger-issue/add-preliminary-comment/preliminary-update.md', - textToFormat: null +/** + * @description - Add label to the issue + * @param {String} labelName - Name of the label to add + */ +async function addLabel(labelName) { + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: [labelName], + }); + } catch(error) { + throw new Error("Error Adding label: " + error); } +} + +/** + * @description - Get latest assignee, in case there are multiple assignees to the issue + * @returns {String} - return the username of the latest assignee + */ +async function getLatestAssignee() { + try { + let issueAssignee = context.payload.issue.assignee.login; + const eventdescriptions = await getTimeline(context.payload.issue.number, github, context); + + // Find out the latest developer assigned to the issue + for(let i = eventdescriptions.length - 1; i >= 0; i -= 1) { + if(eventdescriptions[i].event == 'assigned') { + issueAssignee = eventdescriptions[i].assignee.login; + break; + } + } - // creating the comment with issue assignee's name and returning it! - const commentWithIssueAssignee = formatComment(commentObject, fs) - return commentWithIssueAssignee + return issueAssignee; + } catch(error) { + throw new Error("Error getting last assignee: " + error); + } } - -module.exports = main + +module.exports = main; diff --git a/github-actions/trigger-issue/add-preliminary-comment/unassign-from-NIA.md b/github-actions/trigger-issue/add-preliminary-comment/unassign-from-NIA.md new file mode 100644 index 0000000000..53fd94792e --- /dev/null +++ b/github-actions/trigger-issue/add-preliminary-comment/unassign-from-NIA.md @@ -0,0 +1,5 @@ + + +Hi @${issueAssignee}, HfLA appreciates your interest in this issue, but please note that it is in the **"New Issue Approval"** column of the Project Board because it has not been finalized, approved, or prioritized, and so it is not ready for assignment. For this reason, you have been unassigned from this issue. Please remember to assign issues only from the **"Prioritized Backlog"** column. + +The only exceptions to this rule are if you are writing an issue and the `Draft` label is applied, or if you are self-assigning to your "Pre-work Checklist" (the issue includes the `Complexity: Prework` label). diff --git a/github-actions/trigger-issue/create-codeql-issues/check-existing-issues.js b/github-actions/trigger-issue/create-codeql-issues/check-existing-issues.js new file mode 100644 index 0000000000..d3e18f8547 --- /dev/null +++ b/github-actions/trigger-issue/create-codeql-issues/check-existing-issues.js @@ -0,0 +1,62 @@ +// Global variables +var github; +var context; + +/** + * Fetches existing issues for each alert and sets the output for alerts without existing issues. + * @param {Object} options - The options object. + * @param {string} options.g - The GitHub access token. + * @param {Object} options.c - The context object. + * @param {Array} options.alerts - The array of alerts to check. + * @returns {Promise>} An array of alert IDs without existing issues. + * @throws {Error} If the GET request fails. + */ +const checkExistingIssues = async ({ g, c, alerts }) => { + // Rename parameters + github = g; + context = c; + + // Initialize empty array to store alertIds + let alertIdsWithoutIssues = []; + + // Batch alerts into groups of 5 for each request to avoid rate limit + const batchedAlertIds = alerts.reduce((acc, alert, index) => { + // For indexes 0 to 4, batchIndex == 0 + // For indexes 5 to 9, batchIndex == 1 + // For indexes 10 to 14, batchIndex == 2 + // Etc. + const batchIndex = Math.floor(index / 5); + // if acc[batchIndex] == undefined, a new array is created before pushing the alert number + acc[batchIndex] = acc[batchIndex] || []; + // Push alert.number to inner array + acc[batchIndex].push(alert.number); + // Returns array of arrays + return acc; + }, []); + + // Loop through each batch of alerts + for (const fiveAlertIds of batchedAlertIds) { + // Creates one query for multiple alertIds + const q = fiveAlertIds.map(alertId => `repo:${context.repo.owner}/${context.repo.repo}+state:open+"${alertId}"+in:title`).join('+OR+'); + + // Query GitHub API in batches + const searchResponse = await github.request('GET /search/issues', { q }); + + // Throw error if GET request fails + if (searchResponse.status !== 200) { + throw new Error(`Failed to search for issues: ${searchResponse.status} - ${searchResponse.statusText}`); + } + + // Store the response data in a variable for easy access + const searchResult = searchResponse.data; + + // Push alertIds that do not have existing issues in searchResult to output array + alertIdsWithoutIssues.push(...fiveAlertIds.filter(alertId => !searchResult.items.some(item => item.title.includes(alertId)))); + }; + + // Return flat array of alertIds that do not have issues + console.log('alertIds without issues: ', alertIdsWithoutIssues); + return alertIdsWithoutIssues; +}; + +module.exports = checkExistingIssues diff --git a/github-actions/trigger-issue/create-codeql-issues/create-new-issues.js b/github-actions/trigger-issue/create-codeql-issues/create-new-issues.js new file mode 100644 index 0000000000..a6ab6681fc --- /dev/null +++ b/github-actions/trigger-issue/create-codeql-issues/create-new-issues.js @@ -0,0 +1,52 @@ +const fs = require('fs'); + +// Global variables +var github; +var context; + +/** + * Creates new GitHub issues for each alert that doesn't have an existing issue. + * @param {Object} options - The options object. + * @param {string} options.g - The GitHub access token. + * @param {Object} options.c - The context object. + * @param {Array} options.alertIds - The array of alert IDs to create issues for. + * @returns {Promise} + * @throws {Error} If the POST request fails. + */ +const createNewIssues = async ({ g, c, alertIds }) => { + // Rename parameters + github = g; + context = c; + + // Loop through each alertId + for (const alertId of alertIds) { + // Create the issue title + const title = `Resolve CodeQL Alert #${alertId} - Generated by GHA`; + + // Read the issue body template file + const issueBodyTemplatePath = 'github-actions/trigger-issue/create-codeql-issues/issue-body.md'; + let issueBodyTemplate = fs.readFileSync(issueBodyTemplatePath, 'utf8'); + + // Replace placeholders with actual values in the issue body template + const body = issueBodyTemplate.replace(/\${alertId}/g, alertId); + + // Create a new GitHub issue + const createIssueResponse = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + labels: ['ready for dev lead'] + }); + + // Log issue titles and links in GHA workflow + console.log('Issue Created:', createIssueResponse.data.title, createIssueResponse.data.html_url); + + // Throw error if POST request fails (201 not created) + if (createIssueResponse.status !== 201) { + throw new Error(`Failed to create issue for alert ${alertId}: ${createIssueResponse.status} - ${createIssueResponse.statusText}`); + } + } +}; + +module.exports = createNewIssues; diff --git a/github-actions/trigger-issue/create-codeql-issues/fetch-alerts.js b/github-actions/trigger-issue/create-codeql-issues/fetch-alerts.js new file mode 100644 index 0000000000..94c119d0f3 --- /dev/null +++ b/github-actions/trigger-issue/create-codeql-issues/fetch-alerts.js @@ -0,0 +1,36 @@ +// Global variables +var github; +var context; + +/** + * Fetches a list of open CodeQL alerts from the GitHub API. + * @param {Object} params - The parameters for the fetch operation. + * @param {Object} params.g - The GitHub object for making API requests. + * @param {Object} params.c - The context object containing repository information. + * @returns {Promise} A promise that resolves with an array of alerts when the fetch is successful. + * @throws {Error} If the GET request fails. + */ +const fetchAlerts = async ({ g, c }) => { + // Rename parameters + github = g; + context = c; + + // Get a list of open CodeQL alerts + const fetchAlertsResponse = await github.request('GET /repos/{owner}/{repo}/code-scanning/alerts', { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100, + page: 1 + }); + + // Throw error if GET request fails + if (fetchAlertsResponse.status !== 200) { + throw new Error(`Failed to fetch alerts: ${fetchAlertsResponse.status} - ${fetchAlertsResponse.statusText}`); + } + + // Return alerts + return fetchAlertsResponse.data +}; + +module.exports = fetchAlerts diff --git a/github-actions/trigger-issue/create-codeql-issues/issue-body.md b/github-actions/trigger-issue/create-codeql-issues/issue-body.md new file mode 100644 index 0000000000..45944c29b6 --- /dev/null +++ b/github-actions/trigger-issue/create-codeql-issues/issue-body.md @@ -0,0 +1,27 @@ +### Prerequisite + +1. Be a member of Hack for LA. (There are no fees to join.) If you have not joined yet, please follow the steps on our [Getting Started page](https://www.hackforla.org/getting-started). +2. Before you claim or start working on an issue, please make sure you have read our [How to Contribute to Hack for LA Guide](https://github.com/hackforla/website/blob/7f0c132c96f71230b8935759e1f8711ccb340c0f/CONTRIBUTING.md). + +### Overview +We need to resolve the new alert [(${alertId})](https://github.com/hackforla/website/security/code-scanning/${alertId}) and either recommend dismissal of the alert or update the code files to resolve the alert. + +### Action Items +- [ ] The following action item serves to "link" this issue as the "tracking issue" for the CodeQL alert and to provide more details regarding the alert: +- [ ] https://github.com/hackforla/website/security/code-scanning/${alertId} +- [ ] In a comment in this issue, add your analysis and recommendations. The recommendation can be one of the following: `dismiss as test`, `dismiss as false positive`, `dismiss as won't fix`, or `update code`. An example of a `false positive` is a report of a JavaScript syntax error that is caused by markdown or liquid symbols such as `---` or `{%` +- [ ] **If the recommendation is to dismiss the alert:** + - [ ] Apply the label `ready for dev lead` + - [ ] Move the issue to `Questions/In Review` +- [ ] **If the recommendation is to update code:** + - [ ] Create an issue branch and proceed with the code update + - [ ] Test using docker to ensure that there are no changes to any affected webpage(s) + - [ ] Proceed with pull request in the usual manner + +### Resources/Instructions +- [HfLA website: CodeQL scan alert audits - issue 5005](https://docs.google.com/spreadsheets/d/1B3R-fI8OW0LcYuwZICQZ2fB8sjlE3VsfyGIXoReNBIs/edit#gid=193401043) +- [Code scanning results page](https://github.com/hackforla/website/security/code-scanning) +- [CodeQL query help for JavaScript](https://codeql.github.com/codeql-query-help/javascript/) +- [How to manage CodeQL alerts](https://github.com/hackforla/website/issues/6463#issuecomment-2002573270 ) + +This issue was automatically generated from the codeql.yml workflow \ No newline at end of file diff --git a/github-actions/trigger-issue/feature-branch-comment/add-feature-branch-comment.js b/github-actions/trigger-issue/feature-branch-comment/add-feature-branch-comment.js new file mode 100644 index 0000000000..39b6d69cde --- /dev/null +++ b/github-actions/trigger-issue/feature-branch-comment/add-feature-branch-comment.js @@ -0,0 +1,44 @@ +// Import modules +var fs = require("fs") +const postComment = require("../../utils/post-issue-comment") +const formatComment = require("../../utils/format-comment") + +// Global variables +var github +var context + +/** + * @description - This function is the entry point into the javascript file, it formats the md file and posts the comment on the issue + * @param {Object} g - github object + * @param {Object} c - context object + */ +async function main({ g, c }) { + github = g + context = c + const issueNumber = context.payload.issue.number + const instructions = await makeComment() + if (instructions !== null) { + // the actual creation of the comment in github + await postComment(issueNumber, instructions, github, context) + } +} + +/** + * @description - This function makes the comment with the label event actor's name github handle using the raw feature-branch-comment.md file + * @returns {string} - Comment to be posted with the issue label event actor's name + */ +async function makeComment() { + const commentObject = { + replacementString: context.actor, + placeholderString: "${actor}", + filePathToFormat: + "./github-actions/trigger-issue/feature-branch-comment/feature-branch-comment.md", + textToFormat: null, + } + + // creating the comment with label event actor's name and returning it! + const commentWithEventActor = formatComment(commentObject, fs) + return commentWithEventActor +} + +module.exports = main diff --git a/github-actions/trigger-issue/feature-branch-comment/feature-branch-comment.md b/github-actions/trigger-issue/feature-branch-comment/feature-branch-comment.md new file mode 100644 index 0000000000..07d5daa9f8 --- /dev/null +++ b/github-actions/trigger-issue/feature-branch-comment/feature-branch-comment.md @@ -0,0 +1,5 @@ +Hi @${actor} + +Based on the `Feature: Feature Branch` label, this issue should target a feature branch. + +Please consult the instructions on [working off of a feature branch](https://github.com/hackforla/website/wiki/How-to-work-off-of-a-feature-branch) \ No newline at end of file diff --git a/github-actions/trigger-issue/feature-branch-comment/hide-feature-branch-comment.js b/github-actions/trigger-issue/feature-branch-comment/hide-feature-branch-comment.js new file mode 100644 index 0000000000..c9333fab95 --- /dev/null +++ b/github-actions/trigger-issue/feature-branch-comment/hide-feature-branch-comment.js @@ -0,0 +1,65 @@ +// Import modules to hide comment +const hideComment = require("../../utils/hide-issue-comment") + +// Global variables +var github +var context + +/** + * @description - This function is the entry point into the javascript file, it formats the md file and posts the comment on the issue + * @param {Object} g - github object + * @param {Object} c - context object + */ +async function main({ g, c }) { + github = g + context = c + const comment = await findComment(github, context) + // if the comment exists, then we hide it + if (comment && comment.node_id) { + await hideComment(github, comment.node_id) + } +} + +/** + * @description - fetch comments from GitHub issue + * @returns array of comments, sorted in ascending order by date created + */ +async function fetchComments(github, context) { + let owner = context.repo.owner + let repo = context.repo.repo + const issueNumber = context.payload.issue.number + + const response = await github.rest.issues.listComments({ + owner: owner, + repo: repo, + issue_number: issueNumber, + }) + return response.data +} + +/** + * @description - Goes through an array of comments to find ones with matching body, returns the most recent + * @param {Array} comments array of comments to search through + * @returns most recent comment made with matching `feature: feature branch` + */ +function findMatchingComment(comments) { + const matchingComments = comments.filter((comment) => + comment.body.includes("Feature: Feature Branch") + ) + const comment = matchingComments[matchingComments.length - 1] + if (comment) { + return comment + } + return undefined +} + +/** + * @description - Parent function, will find the most recent matching comment + * @returns matching comment + */ +async function findComment(github, context) { + const comments = await fetchComments(github, context) + return findMatchingComment(comments) +} + +module.exports = main diff --git a/github-actions/trigger-pr-target/verify-pr.js b/github-actions/trigger-pr-target/verify-pr.js new file mode 100644 index 0000000000..9346338a63 --- /dev/null +++ b/github-actions/trigger-pr-target/verify-pr.js @@ -0,0 +1,37 @@ +const isMemberOfTeam = require('../utils/check-team-membership'); +const commentContent = 'You must be a member of the HFLA website team in order to create pull requests. \ +Please see our page on how to join us as a member at HFLA: https://www.hackforla.org/getting-started. \ +If you have been though onboarding, and feel this message was sent in error, please message us in the \ +#hfla-site team Slack channel with the link to this PR.'; + +async function main({github,context}) { + const prAuthor = context.payload.sender.login; + const prNumber = context.payload.number; + const repo = context.payload.pull_request.base.repo.name; + const owner = context.payload.pull_request.base.repo.owner.login; + const isMember = await isMemberOfTeam(github, prAuthor, 'website-write'); + if (isMember || prAuthor =='dependabot[bot]') { + console.log('Successfully verified!'); + } + else { + try { + await github.rest.issues.update({ + owner : owner, + repo : repo, + issue_number : prNumber, + state : 'closed' + }); + await github.rest.issues.createComment({ + owner : owner, + repo : repo, + issue_number : prNumber, + body : commentContent + }); + } catch (closeCommentError) { + console.log(`Failed to close PR #${prNumber} created by ${prAuthor}. See logs for details.`); + throw closeCommentError; + } + } +} + +module.exports = main; diff --git a/github-actions/trigger-pr/check-linked-issue.js b/github-actions/trigger-pr/check-linked-issue.js new file mode 100644 index 0000000000..066edd5b67 --- /dev/null +++ b/github-actions/trigger-pr/check-linked-issue.js @@ -0,0 +1,54 @@ +// Import modules +const postIssueComment = require('../utils/post-issue-comment'); + +// Global variables +var github; +var context; + +async function main({ g, c }) { + github = g; + context = c; + + // Retrieve body of context.payload and search for GitHub keywords followed by + // '#' + number. Exclude any matches that are in a comment within the PR body + const prBody = context.payload.pull_request.body; + const prNumber = context.payload.pull_request.number; + const prOwner = context.payload.pull_request.user.login; + const regex = /(?!)/gi; + const match = prBody.match(regex); + + let prComment; + + if (!match) { + console.log('PR does not have a properly linked issue. Posting comment...'); + prComment = `@${prOwner}, this Pull Request is not linked to a valid issue. Above, on the first line of your PR, please link the number of the issue that you worked on using the format of 'Fixes #' + issue number, for example: **_Fixes #9876_**\n\nNote: Do **_not_** use the number of this PR.`; + } + + else { + console.log(match[0]); + let [ keyword, linkNumber ] = match[0].replaceAll('#','').split(' '); + console.log(`Found a keyword: \'${keyword}\'. Checking for legitimate linked issue...`); + + // Check if the linked issue exists in repo + // https://octokit.github.io/rest.js/v20#issues-get + try { + await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: linkNumber, + }); + console.log(`Found an issue: \'#${linkNumber}\' in repo. Reference is a legitimate linked issue.`); + } + catch (error) { + console.log(`Couldn\'t find issue: \'#${linkNumber}\' in repo. Posting comment...`); + prComment = `@${prOwner}, the issue number referenced above as "**${keyword} #${linkNumber}**" is not found. Please replace with a valid issue number.`; + } + } + + // If the prComment was given text, then post the comment to the PR + if (prComment) { + postIssueComment(prNumber, prComment, github, context); + } +} + +module.exports = main; diff --git a/github-actions/trigger-schedule/add-update-label-weekly/add-label.js b/github-actions/trigger-schedule/add-update-label-weekly/add-label.js index 35cf65c188..d5139e48b1 100644 --- a/github-actions/trigger-schedule/add-update-label-weekly/add-label.js +++ b/github-actions/trigger-schedule/add-update-label-weekly/add-label.js @@ -1,114 +1,156 @@ // Import modules +const fs = require('fs'); +const retrieveLabelDirectory = require('../../utils/retrieve-label-directory'); +const queryIssueInfo = require('../../utils/query-issue-info'); const findLinkedIssue = require('../../utils/find-linked-issue'); const getTimeline = require('../../utils/get-timeline'); -var fs = require("fs"); +const minimizeIssueComment = require('../../utils/hide-issue-comment'); + // Global variables var github; var context; -const statusUpdatedLabel = 'Status: Updated'; -const toUpdateLabel = 'To Update !'; -const inactiveLabel = '2 weeks inactive'; -const updatedByDays = 3; // If there is an update within 3 days, the issue is considered updated -const inactiveUpdatedByDays = 14; // If no update within 14 days, the issue is considered '2 weeks inactive' -const commentByDays = 7; // If there is an update within 14 days but no update within 7 days, the issue is considered outdated and the assignee needs 'To Update !' it -const threeDayCutoffTime = new Date() -threeDayCutoffTime.setDate(threeDayCutoffTime.getDate() - updatedByDays) -const sevenDayCutoffTime = new Date() -sevenDayCutoffTime.setDate(sevenDayCutoffTime.getDate() - commentByDays) -const fourteenDayCutoffTime = new Date() -fourteenDayCutoffTime.setDate(fourteenDayCutoffTime.getDate() - inactiveUpdatedByDays) -/** - * The main function, which retrieves issues from a specific column in a specific project, before examining the timeline of each issue for outdatedness. - * An update to an issue is either 1. a comment by the assignee, or 2. assigning an assignee to the issue. If the last update is not within 7 days or 14 days, apply the according outdate label, and request an update. - * However, if the assignee has submitted a PR that fixed the issue regardless of when, all update-related labels should be removed. +// Use labelKeys to map current labelNames from label directory +const [ + statusUpdated, + statusInactive1, + statusInactive2, + draft, + er, + epic, + dependency, +] = [ + "statusUpdated", + "statusInactive1", + "statusInactive2", + "draft", + "er", + "epic", + "dependency" +].map(retrieveLabelDirectory); + +const updatedByDays = 3; // If last update update 3 days, the issue is considered updated +const commentByDays = 7; // If last update between 7 to 14 days ago, issue is outdated and needs update +const inactiveUpdatedByDays = 14; // If last update greater than 14 days ago, the issue is considered inactive + +const threeDayCutoffTime = new Date(); +threeDayCutoffTime.setDate(threeDayCutoffTime.getDate() - updatedByDays); +const sevenDayCutoffTime = new Date(); +sevenDayCutoffTime.setDate(sevenDayCutoffTime.getDate() - commentByDays); +const fourteenDayCutoffTime = new Date(); +fourteenDayCutoffTime.setDate(fourteenDayCutoffTime.getDate() - inactiveUpdatedByDays); - * @param {Object} g github object from actions/github-script - * @param {Object} c context object from actions/github-script - * @param {Number} columnId a number presenting a specific column to examine, supplied by GitHub secrets + + +/** + * The main function, which retrieves issues from a specific column in a specific project, before examining + * the timeline of each issue for outdatedness. An update to an issue is either 1.) a comment by the assignee, + * or 2.) assigning an assignee to the issue. If the last update was not between 7 to 14 days ago, apply the + * appropriate label and request an update. However, if the assignee has submitted a PR that will fix the issue + * regardless of when, all update-related labels should be removed. + * @param {Object} g - GitHub object from actions/github-script + * @param {Object} c - context object from actions/github-script + * @param {String} projectBoardToken - the Personal Access Token for the action */ -async function main({ g, c }, columnId) { +async function main({ g, c }) { github = g; context = c; - // Retrieve all issue numbers from a column - const issueNums = getIssueNumsFromColumn(columnId); + + // Retrieve all issue numbers from a repo + const issueNums = await getIssueNumsFromRepo(); + for await (let issueNum of issueNums) { const timeline = await getTimeline(issueNum, github, context); - const timelineArray = Array.from(timeline); const assignees = await getAssignees(issueNum); - // Error catching. + // Error catching if (assignees.length === 0) { - console.log(`Assignee not found, skipping issue #${issueNum}`) - continue + console.log(`Issue #${issueNum}: Assignee not found, skipping`); + continue; } - // Add and remove labels as well as post comment if the issue's timeline indicates the issue is inactive, to be updated or up to date accordingly - const responseObject = await isTimelineOutdated(timeline, issueNum, assignees) + // Add and remove labels as well as post comment if the issue's timeline indicates the issue is inactive, to be updated or up-to-date accordingly + const responseObject = await isTimelineOutdated(timeline, issueNum, assignees); - - if (responseObject.result === true && responseObject.labels === toUpdateLabel) { // 7-day outdated, add 'To Update !' label - console.log(`Going to ask for an update now for issue #${issueNum}`); - await removeLabels(issueNum, statusUpdatedLabel, inactiveLabel); + if (responseObject.result === true && responseObject.labels === statusInactive1) { // 7-day outdated: add to be updated label, remove others + await removeLabels(issueNum, statusUpdated, statusInactive2); await addLabels(issueNum, responseObject.labels); - await postComment(issueNum, assignees, toUpdateLabel); - } else if (responseObject.result === true && responseObject.labels === inactiveLabel) { // 14-day outdated, add '2 Weeks Inactive' label - console.log(`Going to ask for an update now for issue #${issueNum}`); - await removeLabels(issueNum, toUpdateLabel, statusUpdatedLabel); + await postComment(issueNum, assignees, statusInactive1); + } else if (responseObject.result === true && responseObject.labels === statusInactive2) { // 14-day outdated: add inactive label, remove others + await removeLabels(issueNum, statusInactive1, statusUpdated); await addLabels(issueNum, responseObject.labels); - await postComment(issueNum, assignees, inactiveLabel); - } else if (responseObject.result === false && responseObject.labels === statusUpdatedLabel) { // Updated within 3 days, retain 'Status: Updated' label if there is one - console.log(`Updated within 3 days, retain updated label for issue #${issueNum}`); - await removeLabels(issueNum, toUpdateLabel, inactiveLabel); - } else if (responseObject.result === false && responseObject.labels === '') { // Updated between 3 and 7 days, or recently assigned, or fixed by a PR by assignee, remove all three update-related labels - console.log(`No updates needed for issue #${issueNum}, will remove all labels`); - await removeLabels(issueNum, toUpdateLabel, inactiveLabel, statusUpdatedLabel); + await postComment(issueNum, assignees, statusInactive2); + } else if (responseObject.result === false && responseObject.labels === statusUpdated) { // Updated within 3 days: retain up-to-date label if there is one + await removeLabels(issueNum, statusInactive1, statusInactive2); + } else if (responseObject.result === false && responseObject.labels === '') { // Updated between 3 and 7 days, or recently assigned, or fixed by a PR by assignee, remove all three update-related labels + await removeLabels(issueNum, statusInactive1, statusInactive2, statusUpdated); } } } + + /** - * Generator that returns issue numbers from cards in a column. - * @param {Number} columnId the id of the column in GitHub's database - * @returns an Array of issue numbers + * Finds issue numbers for all open & assigned issues, excluding issues labeled `Draft`, `ER`, `Epic`, + * or `Dependency`, and returning issue numbers only if their status === "In progess (actively working" + * + * @returns {Promise} issueNums - an array of open, assigned, and statused issue numbers */ -async function* getIssueNumsFromColumn(columnId) { - let page = 1; - while (page < 100) { - try { - const results = await github.rest.projects.listCards({ - column_id: columnId, - per_page: 100, - page: page - }); - if (results.data.length) { - for (let card of results.data) { - if (card.hasOwnProperty('content_url')) { - const arr = card.content_url.split('/'); - yield arr.pop() - } - } - } else { - return - } - } catch { - continue - } finally { - page++; +async function getIssueNumsFromRepo() { + const labelsToExclude = [draft, er, epic, dependency]; + let issueNums = []; + let pageNum = 1; + let result = []; + + while (true) { + // https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#list-repository-issues + const issueData = await github.request('GET /repos/{owner}/{repo}/issues', { + owner: context.repo.owner, + repo: context.repo.repo, + assignee: '*', + per_page: 100, + page: pageNum, + }); + + if (!issueData.data.length) { + break; + } else { + result = result.concat(issueData.data); + pageNum++; + } + } + + for (let { number, labels, pull_request } of result) { + if (!number) continue; + + // Exclude any pull requests that were found + if (pull_request != undefined) continue; + + // Exclude any issues that have excluded labels + const issueLabels = labels.map((label) => label.name); + if (issueLabels.some((item) => labelsToExclude.includes(item))) continue; + + // For remaining issues, check if status === "In progress (actively working)" + const { statusName } = await queryIssueInfo(github, context, number); + if (statusName === "In progress (actively working)") { + issueNums.push(number); } } + return issueNums; } + + /** * Assesses whether the timeline is outdated. - * @param {Array} timeline a list of events in the timeline of an issue, retrieved from the issues API - * @param {Number} issueNum the issue's number - * @param {String} assignees a list of the issue's assignee's username + * @param {Array} timeline - a list of events in the timeline of an issue, retrieved from the issues API + * @param {Number} issueNum - the issue's number + * @param {String} assignees - a list of the issue's assignee's username * @returns true if timeline indicates the issue is outdated/inactive, false if not; also returns appropriate labels that should be retained or added to the issue */ - function isTimelineOutdated(timeline, issueNum, assignees) { // assignees is an arrays of `login`'s let lastAssignedTimestamp = null; let lastCommentTimestamp = null; + let commentsToBeMinimized = []; for (let i = timeline.length - 1; i >= 0; i--) { let eventObj = timeline[i]; @@ -120,14 +162,14 @@ function isTimelineOutdated(timeline, issueNum, assignees) { // assignees is an // request is open, remove all update-related labels // Once a PR is opened, we remove labels because we focus on the PR not the issue. if (isOpenLinkedPullRequest && assignees.includes(eventObj.actor.login)) { - console.log(`Assignee fixes/resolves/closes Issue #${issueNum} in with an open pull request, remove all update-related labels`); - return { result: false, labels: '' } // remove all three labels + console.log(`Issue #${issueNum}: Assignee fixes/resolves/closes issue with an open pull request, remove all update-related labels`); + return { result: false, labels: '' }; // remove all three labels } // If the event is a linked PR and the PR is closed, it will continue through the // rest of the conditions to receive the appropriate label. else if(eventType === 'cross-referenced' && eventObj.source.issue.state === 'closed') { - console.log(`Pull request linked to Issue #${issueNum} is closed.`); + console.log(`Issue #${issueNum}: Linked pull request has been closed.`); } let eventTimestamp = eventObj.updated_at || eventObj.created_at; @@ -141,86 +183,107 @@ function isTimelineOutdated(timeline, issueNum, assignees) { // assignees is an else if (!lastAssignedTimestamp && eventType === 'assigned' && assignees.includes(eventObj.assignee.login)) { lastAssignedTimestamp = eventTimestamp; } + + // If this event is more than 7 days old AND this event is a comment by the GitHub Actions Bot, then hide the comment as outdated. + if (!isMomentRecent(eventObj.created_at, sevenDayCutoffTime) && eventType === 'commented' && isCommentByBot(eventObj)) { + console.log(`Comment ${eventObj.node_id} is outdated (i.e. > 7 days old) and will be minimized.`); + commentsToBeMinimized.push(eventObj.node_id); // retain node id so its associated comment can be minimized later + } } + minimizeComments(commentsToBeMinimized); + if (lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, threeDayCutoffTime)) { // if commented by assignee within 3 days - console.log(`Issue #${issueNum} commented by assignee within 3 days, retain 'Status: Updated' label`); - return { result: false, labels: statusUpdatedLabel } // retain (don't add) updated label, remove the other two + console.log(`Issue #${issueNum}: Commented by assignee within 3 days, retain '${statusUpdated}' label`); + return { result: false, labels: statusUpdated } // retain (don't add) updated label, remove the other two } if (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, threeDayCutoffTime)) { // if an assignee was assigned within 3 days - console.log(`Issue #${issueNum} assigned to assignee within 3 days, no update-related labels should be used`); + console.log(`Issue #${issueNum}: Assigned to assignee within 3 days, no update-related labels should be used`); return { result: false, labels: '' } // remove all three labels } if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, sevenDayCutoffTime)) || (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, sevenDayCutoffTime))) { // if updated within 7 days if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, sevenDayCutoffTime))) { - console.log(`Issue #${issueNum} commented by assignee between 3 and 7 days, no update-related labels should be used; timestamp: ${lastCommentTimestamp}`) + console.log(`Issue #${issueNum}: Commented by assignee between 3 and 7 days, no update-related labels should be used; timestamp: ${lastCommentTimestamp}`) } else if (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, sevenDayCutoffTime)) { - console.log(`Issue #${issueNum} assigned between 3 and 7 days, no update-related labels should be used; timestamp: ${lastAssignedTimestamp}`) + console.log(`Issue #${issueNum}: Assigned between 3 and 7 days, no update-related labels should be used; timestamp: ${lastAssignedTimestamp}`) } return { result: false, labels: '' } // remove all three labels } - if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, fourteenDayCutoffTime)) || (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, fourteenDayCutoffTime))) { // if last comment was between 7-14 days, or no comment but an assginee was assigned during this period, issue is outdated and add 'To Update !' label + if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, fourteenDayCutoffTime)) || (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, fourteenDayCutoffTime))) { // if last comment was between 7-14 days, or no comment but an assginee was assigned during this period, issue is outdated and add needs update label if ((lastCommentTimestamp && isMomentRecent(lastCommentTimestamp, fourteenDayCutoffTime))) { - console.log(`Issue #${issueNum} commented by assignee between 7 and 14 days, use 'To Update !' label; timestamp: ${lastCommentTimestamp}`) + console.log(`Issue #${issueNum}: Commented by assignee between 7 and 14 days, use '${statusInactive1}' label; timestamp: ${lastCommentTimestamp}`) } else if (lastAssignedTimestamp && isMomentRecent(lastAssignedTimestamp, fourteenDayCutoffTime)) { - console.log(`Issue #${issueNum} assigned between 7 and 14 days, use 'To Update !' label; timestamp: ${lastAssignedTimestamp}`) + console.log(`Issue #${issueNum}: Assigned between 7 and 14 days, use '${statusInactive1}' label; timestamp: ${lastAssignedTimestamp}`) } - return { result: true, labels: toUpdateLabel } // outdated, add 'To Update!' label + return { result: true, labels: statusInactive1 } // outdated, add needs update label } - // if no comment or assigning found within 14 days, issue is outdated and add '2 weeks inactive' label - console.log(`Issue #${issueNum} has no update within 14 days, use '2 weeks inactive' label`) - return { result: true, labels: inactiveLabel } + // If no comment or assigning found within 14 days, issue is outdated and add inactive label + console.log(`Issue #${issueNum}: No update within 14 days, use '${statusInactive2}' label`) + return { result: true, labels: statusInactive2 } } + + /** * Removes labels from a specified issue - * @param {Number} issueNum an issue's number - * @param {Array} labels an array containing the labels to remove (captures the rest of the parameters) + * @param {Number} issueNum - an issue's number + * @param {Array} labels - an array containing the labels to remove (captures the rest of the parameters) */ async function removeLabels(issueNum, ...labels) { for (let label of labels) { try { - // https://octokit.github.io/rest.js/v18#issues-remove-label - await github.rest.issues.removeLabel({ + // https://docs.github.com/en/rest/issues/labels?apiVersion=2022-11-28#remove-a-label-from-an-issue + await github.request('DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}', { owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNum, name: label, }); - console.log(`Removed "${label}" from issue #${issueNum}`); + console.log(` '${label}' label has been removed`); } catch (err) { - console.error(`Function failed to remove labels. Please refer to the error below: \n `, err); + if (err.status === 404) { + console.log(` '${label}' label not found, no need to remove`); + } else { + console.error(`Function failed to remove labels. Please refer to the error below: \n `, err); + } } } } + + + /** * Adds labels to a specified issue - * @param {Number} issueNum an issue's number - * @param {Array} labels an array containing the labels to add (captures the rest of the parameters) + * @param {Number} issueNum -an issue's number + * @param {Array} labels -an array containing the labels to add (captures the rest of the parameters) */ async function addLabels(issueNum, ...labels) { try { - // https://octokit.github.io/rest.js/v18#issues-add-labels + // https://octokit.github.io/rest.js/v20#issues-add-labels await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNum, labels: labels, }); - console.log(`Added these labels to issue #${issueNum}: ${labels}`); + console.log(` '${labels}' label has been added`); // If an error is found, the rest of the script does not stop. } catch (err) { console.error(`Function failed to add labels. Please refer to the error below: \n `, err); } } + + + async function postComment(issueNum, assignees, labelString) { try { const assigneeString = createAssigneeString(assignees); const instructions = formatComment(assigneeString, labelString); + // https://octokit.github.io/rest.js/v20/#issues-create-comment await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, @@ -231,26 +294,29 @@ async function postComment(issueNum, assignees, labelString) { console.error(`Function failed to post comments. Please refer to the error below: \n `, err); } } + + + /*********************** *** HELPER FUNCTIONS *** ***********************/ function isMomentRecent(dateString, cutoffTime) { const dateStringObj = new Date(dateString); - if (dateStringObj >= cutoffTime) { - return true + return true; } else { - return false + return false; } } - function isLinkedIssue(data, issueNum) { return findLinkedIssue(data.source.issue.body) == issueNum } + function isCommentByAssignees(data, assignees) { - return assignees.includes(data.actor.login) + return assignees.includes(data.actor.login); } + async function getAssignees(issueNum) { try { const results = await github.rest.issues.get({ @@ -259,38 +325,55 @@ async function getAssignees(issueNum) { issue_number: issueNum, }); const assigneesData = results.data.assignees; - assigneesLogins = filterForAssigneesLogins(assigneesData); - return assigneesLogins + const assigneesLogins = filterForAssigneesLogins(assigneesData); + return assigneesLogins; } catch (err) { console.error(`Function failed to get assignees. Please refer to the error below: \n `, err); - return null + return null; } } + function filterForAssigneesLogins(data) { - logins = []; + const logins = []; for (let item of data) { logins.push(item.login); } - return logins + return logins; } + function createAssigneeString(assignees) { const assigneeString = []; for (let assignee of assignees) { assigneeString.push(`@${assignee}`); } - return assigneeString.join(', ') + return assigneeString.join(', '); } + function formatComment(assignees, labelString) { - const path = './github-actions/trigger-schedule/add-update-label-weekly/update-instructions-template.md' + const path = './github-actions/trigger-schedule/add-update-label-weekly/update-instructions-template.md'; const text = fs.readFileSync(path).toString('utf-8'); const options = { dateStyle: 'full', timeStyle: 'short', timeZone: 'America/Los_Angeles', - } + }; const cutoffTimeString = threeDayCutoffTime.toLocaleString('en-US', options); let completedInstuctions = text.replace('${assignees}', assignees).replace('${cutoffTime}', cutoffTimeString).replace('${label}', labelString); - return completedInstuctions + return completedInstuctions; +} + +function isCommentByBot(data) { + let botLogin = "github-actions[bot]"; + let hflaBotLogin = "HackforLABot"; + return data.actor.login === botLogin || data.actor.login === hflaBotLogin; +} + +// asynchronously minimize all the comments that are outdated (> 1 week old) +async function minimizeComments(comment_node_ids) { + for (const node_id of comment_node_ids) { + await new Promise((resolve) => { setTimeout(resolve, 1000); }); // wait for 1000ms before doing the GraphQL mutation + await minimizeIssueComment(github, node_id); + } } -module.exports = main +module.exports = main; diff --git a/github-actions/trigger-schedule/github-data/contributors-data.js b/github-actions/trigger-schedule/github-data/contributors-data.js deleted file mode 100644 index a2320c45f5..0000000000 --- a/github-actions/trigger-schedule/github-data/contributors-data.js +++ /dev/null @@ -1,374 +0,0 @@ -const fs = require("fs"); -const { Octokit } = require("@octokit/rest"); - -// Extend Octokit with new contributor endpoints and construct instance of class with Auth token -Object.assign(Octokit.prototype); -const octokit = new Octokit({ auth: process.env.token }); - -// Set variables to avoid hard-coding -const org = 'hackforla'; -const repo = 'website'; -const team = 'website-write'; -const baseTeam = 'website'; -const maintTeam = 'website-maintain'; - -// Set date limits: we are sorting inactive members into groups to warn after 1 month and remove after 2 months. -// Since the website team takes off the month of December, the January 1st run is skipped (via `schedule-monthly.yml`). -// The February 1st run keeps the 1 month inactive warning, but changes removal to 3 months inactive (skipping December). -let today = new Date(); -let oneMonth = (today.getMonth() == 1) ? 2 : 1; // If month is "February" == 1, then oneMonth = 2 months ago -let twoMonths = (today.getMonth() == 1) ? 3 : 2; // If month is "February" == 1, then twoMonths = 3 months ago - -let oneMonthAgo = new Date(); // oneMonthAgo instantiated with date of "today" -oneMonthAgo.setMonth(oneMonthAgo.getMonth() - oneMonth); // then set oneMonthAgo from "today" -oneMonthAgo = oneMonthAgo.toISOString(); -let twoMonthsAgo = new Date(); // twoMonthsAgo instantiated with date of "today" -twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - twoMonths); // then set twoMonthsAgo from "today" -twoMonthsAgo = twoMonthsAgo.toISOString(); - - - -/** - * Main function, immediately invoked - */ -(async function main(){ - const [contributorsOneMonthAgo, contributorsTwoMonthsAgo, inactiveWithOpenIssue] = await fetchContributors(); - console.log('-------------------------------------------------------'); - console.log('List of active contributors since ' + oneMonthAgo.slice(0, 10) + ':'); - console.log(contributorsOneMonthAgo); - - const currentTeamMembers = await fetchTeamMembers(team); - console.log('-------------------------------------------------------'); - console.log('Current members of ' + team + ':') - console.log(currentTeamMembers) - - const [removedContributors, cannotRemoveYet] = await removeInactiveMembers(currentTeamMembers, contributorsTwoMonthsAgo, inactiveWithOpenIssue); - console.log('-------------------------------------------------------'); - console.log('Removed members from ' + team + ' inactive since ' + twoMonthsAgo.slice(0, 10) + ':'); - console.log(removedContributors); - - console.log('-------------------------------------------------------'); - console.log('Members inactive since ' + twoMonthsAgo.slice(0, 10) + ' with open issues preventing removal:'); - console.log(cannotRemoveYet); - - const updatedTeamMembers = await fetchTeamMembers(team); - const notifiedContributors = await notifyInactiveMembers(updatedTeamMembers, contributorsOneMonthAgo); - console.log('-------------------------------------------------------'); - console.log('Notified members from ' + team + ' inactive since ' + oneMonthAgo.slice(0, 10) + ':'); - console.log(notifiedContributors); - - writeData(removedContributors, notifiedContributors); -})(); - - - -/** - * Function to fetch list of contributors with comments/commits/issues since date - * @returns {Object} allContributorsSinceOneMonthAgo - List of active contributors since one month ago - * @returns {Object} allContributorsSinceTwoMonthsAgo - List of active contributors since two months ago - */ -async function fetchContributors(){ - let allContributorsSinceOneMonthAgo = {}; - let allContributorsSinceTwoMonthsAgo = {}; - let inactiveWithOpenIssue = {}; - - // Members on 'website-maintain' team considered permanent members - const permanentMembers = await fetchTeamMembers(maintTeam); - - // Fetch all contributors with commit, comment, and issue (assignee) contributions - const APIs = ['GET /repos/{owner}/{repo}/commits', 'GET /repos/{owner}/{repo}/issues/comments', 'GET /repos/{owner}/{repo}/issues']; - const dates = [oneMonthAgo, twoMonthsAgo]; - - for (const date of dates){ - const allContributorsSince = {}; - for(const api of APIs){ - let pageNum = 1; - let result = []; - - // Since Github only allows to fetch max 100 items per request, we need to 'flip' pages - while(true){ - // Fetch 100 items per each page (`pageNum`) - const contributors = await octokit.request(api, { - owner: org, - repo: repo, - since: date, - per_page: 100, - page: pageNum - }); - - // If the API call returns an empty array, break out of loop- there is no additional data. - // Else if data is returned, push it to `result` and increase the page number (`pageNum`) - if(!contributors.data.length){ - break; - } else { - result = result.concat(contributors.data); - pageNum++; - } - } - - // Once we have looked at all pages and collected all the data, we create key-value pairs of recent contributors and store - // them in the `allContributorsSince` object. The contributor data that comes back from each API are stored differently, - // i.e. `author.login` vs `user.login` vs `assignee.login`. We want to extract the contributors' usernames for each situation. - for(const contributorInfo of result){ - // Check if username is stored in `author.login` - if(contributorInfo.author){ - allContributorsSince[contributorInfo.author.login] = true; - } - // Check for username in `user.login`, but skip `user.login` covered by 3rd API - else if(contributorInfo.user && api != 'GET /repos/{owner}/{repo}/issues'){ - allContributorsSince[contributorInfo.user.login] = true; - } - // This check is done for `/issues` (3rd) API. Sometimes a user who created an issue is not the same as the - // assignee on that issue- we want to make sure that we count all assignees as active contributors as well. - // We only want to run this check if the assignee is not counted as an active contributor yet. - else if((contributorInfo.assignee) && (contributorInfo.assignee.login in allContributorsSince === false)){ - const issueNum = contributorInfo.number; - const timeline = await getEventTimeline(issueNum); - const assignee = contributorInfo.assignee.login; - const responseObject = await isEventOutdated(date, timeline, assignee); - // If timeline is not outdated, add member to `allContributorsSince` - if(responseObject.result === false){ - allContributorsSince[assignee] = true; - } - // If timeline is more than two months ago, and the issue title does not include - // the words "Pre-work Checklist", add to open issues with inactive comments - else { - if(date == twoMonthsAgo && !contributorInfo.title.includes("Pre-work Checklist")){ - inactiveWithOpenIssue[assignee] = issueNum; - } - } - } - } - } - // Add permanent members from 'website-maintain' to list of active contributors - for(const permanentMember in permanentMembers){ - allContributorsSince[permanentMember] = true; - } - if(date == oneMonthAgo){ - allContributorsSinceOneMonthAgo = allContributorsSince; - } else { - allContributorsSinceTwoMonthsAgo = allContributorsSince; - } - } - return [allContributorsSinceOneMonthAgo, allContributorsSinceTwoMonthsAgo, inactiveWithOpenIssue]; -} - - -/* - * Helper functions for fetchContributors() - * - * - */ -async function getEventTimeline(issueNum) { - let timelineArray = [] - let page = 1 - while (true) { - try { - const results = await octokit.rest.issues.listEventsForTimeline({ - owner: org, - repo: repo, - issue_number: issueNum, - per_page: 100, - page: page, - }); - if (results.data.length) { - timelineArray = timelineArray.concat(results.data); - } else { - break - } - } catch (err) { - console.log(err); - continue - } - finally { - page++ - } - } - return timelineArray -} - - -function isEventOutdated(date, timeline, assignee) { - let lastAssignedTimestamp = null; - for (let i = timeline.length - 1; i >= 0; i--) { - let eventObj = timeline[i]; - let eventType = eventObj.event; - let eventTimestamp = eventObj.updated_at || eventObj.created_at; - - // update the lastAssignedTimestamp if this is the last (most recent) time an assignee was assigned to the issue - if (!lastAssignedTimestamp && eventType === 'assigned' && assignee === (eventObj.assignee.login)) { - lastAssignedTimestamp = eventTimestamp; - } - } - // If the assignee was assigned later than the 'date', the issue is not outdated so return false - if (lastAssignedTimestamp && (lastAssignedTimestamp >= date)) { - return { result: false }; - } - return { result: true }; -} - - - -/** - * Function to return list of current team members - * @param {String} team_slug - default to 'website-write' team - * @returns {Array} allMembers - Current team members - */ -async function fetchTeamMembers(fetchTeam){ - - let pageNum = 1; - let teamResults = []; - - // Fetch all members of team. Note: if total members exceed 100, we need to 'flip' pages - while(true){ - const teamMembers = await octokit.request('GET /orgs/{org}/teams/{team_slug}/members', { - org: org, - team_slug: fetchTeam, - per_page: 100, - page: pageNum - }) - if(!teamMembers.data.length){ - break; - } else { - teamResults = teamResults.concat(teamMembers.data); - pageNum++; - } - } - const allMembers = {}; - for(const member of teamResults){ - allMembers[member.login] = true; - } - return allMembers; -} - - - -/** - * Function to return list of contributors that have been inactive since twoMonthsAgo - * @param {Object} currentTeamMembers - List of active team members - * @param {Object} recentContributors - List of active contributors - * @returns {Array} removed members - List of members that were removed - */ -async function removeInactiveMembers(currentTeamMembers, recentContributors, inactiveWithOpenIssue){ - const removedMembers = []; - const cannotRemoveYet = {}; - - // Loop over team members and remove them from the team if they are not in recentContributors - for(const username in currentTeamMembers){ - if (!recentContributors[username]){ - // Prior to deletion, confirm that member is on the 'base' === 'website' team - const baseMember = await octokit.request('GET /orgs/{org}/teams/{team_slug}/memberships/{username}', { - org: org, - team_slug: baseTeam, - username: username, - }) - // If response status is not 200, need to add member to 'base' team before deleting - if(baseMember.status != 200){ - await octokit.request('PUT /orgs/{org}/teams/{team_slug}/memberships/{username}', { - org: org, - team_slug: baseTeam, - username: username, - role: 'member', - }) - console.log('Member added to \'website\' team: ' + username); - } - // Remove member from the team if they don't pass additional checks in `shouldRemoveOrNotify` function - if(await shouldRemoveOrNotify(username)){ - // But if member has an open issue, don't remove - if(username in inactiveWithOpenIssue){ - cannotRemoveYet[username] = inactiveWithOpenIssue[username]; - } else { - await octokit.request('DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}', { - org: org, - team_slug: team, - username: username, - }) - removedMembers.push(username); - } - } - } - } - return [removedMembers, cannotRemoveYet]; -} - - - -/** - * Function to check if a member is set for removal - * @param {String} member - Member's username - * @returns {Boolean} - true/false - */ -async function shouldRemoveOrNotify(member){ - - // Get member's membership status: if member is a team 'Maintainer', return false- we don't remove maintainers - const membershipStatus = await octokit.request('GET /orgs/{org}/teams/{team_slug}/memberships/{username}', { - org: org, - team_slug: team, - username: member, - }) - if(membershipStatus.data.role === 'maintainer'){ - console.log("This inactive member is a 'Maintainer': " + member); - return false; - } - - // Run check to see if member cloned the 'website' repo within the last 30 days. If so do not notify - // because they are new members. (This will not catch new members who did not name their repos 'website'.) - try { - const repoData = await octokit.request('GET /repos/{username}/{repo}', { - username: member, - repo: repo, - }); - if(repoData.created_at > oneMonthAgo){ - return false; - } - } catch {} - - // Else this member is inactive and should be notified or removed from team - return true; -} - - - -/** - * Function to return list of contributors that have been inactive since oneMonthAgo - * @param {Array} updatedTeamMembers - List of updated team members - * @param {Array} recentContributors - List of recent contributors - * @returns {Array} - List of members to be notified (that they are on the list to be removed) - */ -async function notifyInactiveMembers(updatedTeamMembers, recentContributors){ - const notifiedMembers = []; - - // Loop over team members and add to "notify" list if they are not in recentContributors - for(const username in updatedTeamMembers){ - if (!recentContributors[username]){ - // Check whether member should be added to notifiedMembers list - if(await shouldRemoveOrNotify(username)){ - notifiedMembers.push(username) - } - } - } - return notifiedMembers; -} - - - -/** - * Function to save inactive members list to local for use in next job - * @param {Array} removedContributors - List of removed contributors - * @param {Array} notifiedContributors - List of contributors to be notified - * @returns {void} - */ -function writeData(removedContributors, notifiedContributors){ - - // Combine removed and notified contributor lists into one dict - let inactiveMemberLists = {}; - inactiveMemberLists["removedContributors"] = removedContributors; - inactiveMemberLists["notifiedContributors"] = notifiedContributors; - - fs.writeFile('inactive-Members.json', JSON.stringify(inactiveMemberLists, null, 2), (err) => { - if (err) throw err; - console.log('-------------------------------------------------------'); - console.log("File 'inactive-Members.json' saved successfully!"); - }); - -} diff --git a/github-actions/trigger-schedule/github-data/get-project-data.js b/github-actions/trigger-schedule/github-data/get-project-data.js index 7f8f33ba8e..ae99279755 100644 --- a/github-actions/trigger-schedule/github-data/get-project-data.js +++ b/github-actions/trigger-schedule/github-data/get-project-data.js @@ -1,15 +1,15 @@ -const core = require("@actions/core"); -const fs = require("fs"); -const { Octokit } = require("@octokit/rest"); -const trueContributorsMixin = require("true-github-contributors"); -const _ = require('lodash'); +// @octokit/rest revised from v20.0.1 to v21.0.0 suggested +// by dependabot. *** Package v21.0.0 is now ESM *** +import fs from "fs"; +import { Octokit } from "@octokit/rest"; +import trueContributorsMixin from "true-github-contributors"; +import _ from "lodash"; // Record the time this script started running so it can be stored later const dateRan = new Date(); // Hard coded list of untagged repos we would like to fetch data on // 79977929 -> https://github.com/hunterowens/workfor.la -// 277577906 -> https://github.com/codeforamerica/brigade-playbook -const untaggedRepoIds = [79977929, 277577906]; +const untaggedRepoIds = [79977929]; // Extend Octokit with new contributor endpoints and construct instance of class with API token @@ -92,7 +92,7 @@ function getLocalData(){ */ function projectListToMap(projectList) { let projectMap = {}; - for(project of projectList){ + for(let project of projectList){ projectMap[project.id] = project; } return projectMap; @@ -103,14 +103,28 @@ function projectListToMap(projectList) { * @return {Array} [Array of GitHub repository objects] */ async function getAllRepos() { - let allRepos = []; - let taggedRepos = await octokit.paginate(octokit.search.repos, {q: "topic:hack-for-la"}); - allRepos = taggedRepos; - for(let i = 0; i < untaggedRepoIds.length; i++){ - let untaggedRepo = await octokit.request("GET /repositories/:id", { id: untaggedRepoIds[i] }); - allRepos.push(untaggedRepo.data); + let tries = 0; + const delay = (length) => new Promise((resolve) => setTimeout(resolve, length)); + + while(tries < 4) { + try{ + let allRepos = []; + let taggedRepos = await octokit.paginate(octokit.search.repos, {q: "topic:hack-for-la"}); + allRepos = taggedRepos; + for(let i = 0; i < untaggedRepoIds.length; i++) { + let untaggedRepo = await octokit.request("GET /repositories/:id", { id: untaggedRepoIds[i] }); + allRepos.push(untaggedRepo.data); + } + return allRepos; + } catch(error) { + if(tries === 3) { + throw error; + } else { + await delay(2**tries*120000); + tries++; + } + } } - return allRepos; } /** @@ -181,7 +195,7 @@ function constructContributorParams(repo) { */ function formatContributorsList(contributorsList){ for(let i = 0; i < contributorsList.length; i++){ - currentContributor = contributorsList[i]; + const currentContributor = contributorsList[i]; contributorsList[i] = { id: currentContributor.id, github_url: currentContributor.html_url, diff --git a/github-actions/trigger-schedule/github-data/package-lock.json b/github-actions/trigger-schedule/github-data/package-lock.json index 2e2beefcf3..9ef0eb486c 100644 --- a/github-actions/trigger-schedule/github-data/package-lock.json +++ b/github-actions/trigger-schedule/github-data/package-lock.json @@ -1,48 +1,76 @@ { "name": "Website", - "version": "2.0.0", - "lockfileVersion": 1, + "version": "3.0.0", + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@actions/core": { + "packages": { + "": { + "name": "Website", + "version": "3.0.0", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/github": "^6.0.0", + "@actions/http-client": ">=2.2.1", + "@octokit/rest": "^21.0.0", + "lodash": "^4.17.21", + "true-github-contributors": "^1.0.5" + }, + "devDependencies": {}, + "engines": { + "node": ">=18" + } + }, + "node_modules/@actions/core": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", - "requires": { + "dependencies": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" } }, - "@actions/github": { + "node_modules/@actions/github": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", - "requires": { + "dependencies": { "@actions/http-client": "^2.2.0", "@octokit/core": "^5.0.1", "@octokit/plugin-paginate-rest": "^9.0.0", "@octokit/plugin-rest-endpoint-methods": "^10.0.0" } }, - "@actions/http-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", - "integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==", - "requires": { + "node_modules/@actions/http-client": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", + "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, - "@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==" + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "engines": { + "node": ">= 18" + } }, - "@octokit/core": { + "node_modules/@octokit/core": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz", "integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==", - "requires": { + "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.0.0", "@octokit/request": "^8.0.2", @@ -51,178 +79,356 @@ "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/endpoint": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz", + "integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==", "dependencies": { - "@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==" - }, - "@octokit/endpoint": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz", - "integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==", - "requires": { - "@octokit/types": "^12.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", - "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", - "requires": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.2.tgz", - "integrity": "sha512-A0RJJfzjlZQwb+39eDm5UM23dkxbp28WEG4p2ueH+Q2yY4p349aRK/vcUlEuIB//ggcrHJceoYYkBP/LYCoXEg==", - "requires": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", - "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", - "requires": { - "@octokit/types": "^12.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "requires": { - "@octokit/openapi-types": "^19.0.0" - } - } - } - }, - "@octokit/openapi-types": { + "@octokit/types": "^12.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/graphql": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", + "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", + "dependencies": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^12.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/request": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.2.tgz", + "integrity": "sha512-A0RJJfzjlZQwb+39eDm5UM23dkxbp28WEG4p2ueH+Q2yY4p349aRK/vcUlEuIB//ggcrHJceoYYkBP/LYCoXEg==", + "dependencies": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/request-error": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", + "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", + "dependencies": { + "@octokit/types": "^12.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dependencies": { + "@octokit/openapi-types": "^19.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "dependencies": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint/node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" + }, + "node_modules/@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" + }, + "node_modules/@octokit/openapi-types": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==" }, - "@octokit/plugin-paginate-rest": { + "node_modules/@octokit/plugin-paginate-rest": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz", "integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==", - "requires": { + "dependencies": { "@octokit/types": "^12.0.0" }, - "dependencies": { - "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "requires": { - "@octokit/openapi-types": "^19.0.0" - } - } + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" } }, - "@octokit/plugin-request-log": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz", - "integrity": "sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==" + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dependencies": { + "@octokit/openapi-types": "^19.0.0" + } }, - "@octokit/plugin-rest-endpoint-methods": { + "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz", "integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==", - "requires": { + "dependencies": { "@octokit/types": "^12.0.0" }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", "dependencies": { - "@octokit/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", - "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", - "requires": { - "@octokit/openapi-types": "^19.0.0" - } - } + "@octokit/openapi-types": "^19.0.0" } }, - "@octokit/rest": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-20.0.2.tgz", - "integrity": "sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==", - "requires": { - "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-request-log": "^4.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + "node_modules/@octokit/request": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", + "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz", + "integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==", + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request/node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" + }, + "node_modules/@octokit/rest": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.0.1.tgz", + "integrity": "sha512-RWA6YU4CqK0h0J6tfYlUFnH3+YgBADlxaHXaKSG+BVr2y4PTfbU2tlKuaQoQZ83qaTbi4CUxLNAmbAqR93A6mQ==", + "dependencies": { + "@octokit/core": "^6.1.2", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz", + "integrity": "sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==", + "dependencies": { + "@octokit/types": "^13.5.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.4.tgz", + "integrity": "sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw==", + "dependencies": { + "@octokit/types": "^13.5.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" } }, - "before-after-hook": { + "node_modules/@octokit/rest/node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==" + }, + "node_modules/@octokit/rest/node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" + }, + "node_modules/@octokit/types": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@octokit/types/node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==" + }, + "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, - "deprecation": { + "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, - "is-plain-object": { + "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { + "dependencies": { "wrappy": "1" } }, - "true-github-contributors": { + "node_modules/true-github-contributors": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/true-github-contributors/-/true-github-contributors-1.0.5.tgz", "integrity": "sha512-E7+yRCs+8iigmNML74g1T72wV32Ny8mr4KttrviHtXlU0Lw1UNTF7EOJ/vg8Cz+usc5DOfKixlorLoBLw639aQ==" }, - "tunnel": { + "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } }, - "undici": { - "version": "5.28.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", - "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", - "requires": { + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" } }, - "universal-user-agent": { + "node_modules/universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" }, - "uuid": { + "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" diff --git a/github-actions/trigger-schedule/github-data/package.json b/github-actions/trigger-schedule/github-data/package.json index fefb98cf51..695803bd76 100644 --- a/github-actions/trigger-schedule/github-data/package.json +++ b/github-actions/trigger-schedule/github-data/package.json @@ -1,13 +1,17 @@ { "name": "Website", - "version": "2.0.0", + "version": "3.0.0", "description": "> Hack for LA's website https://www.hackforla.org", - "main": "./github-actions/get-project-data.js", + "exports": "./github-actions/get-project-data.js", + "type": "module", + "engines": { + "node": ">=18" + }, "dependencies": { "@actions/core": "^1.10.1", "@actions/github": "^6.0.0", - "@actions/http-client": ">=2.2.0", - "@octokit/rest": "^20.0.2", + "@actions/http-client": ">=2.2.1", + "@octokit/rest": "^21.0.0", "lodash": "^4.17.21", "true-github-contributors": "^1.0.5" }, diff --git a/github-actions/trigger-schedule/list-inactive-members/create-new-issue.js b/github-actions/trigger-schedule/list-inactive-members/create-new-issue.js index e4421eda52..8dcf9f731e 100644 --- a/github-actions/trigger-schedule/list-inactive-members/create-new-issue.js +++ b/github-actions/trigger-schedule/list-inactive-members/create-new-issue.js @@ -1,4 +1,5 @@ // Import modules +const fs = require('fs'); const issueTemplateParser = require('../../utils/issue-template-parser'); const postComment = require('../../utils/post-issue-comment'); @@ -6,12 +7,15 @@ const postComment = require('../../utils/post-issue-comment'); var github; var context; -async function main({ g, c }, artifactContent) { +async function main({ g, c }) { github = g; context = c; // Retrieve lists data from json file written in previous step - let inactiveLists = JSON.parse(artifactContent); + const filepath = 'github-actions/utils/_data/inactive-members.json'; + const rawData = fs.readFileSync(filepath, 'utf8'); + let inactiveLists = JSON.parse(rawData); + const inactiveWithOpen = parseInactiveOpen(inactiveLists['cannotRemoveYet']); const owner = context.repo.owner; const repo = context.repo.repo; @@ -19,16 +23,10 @@ async function main({ g, c }, artifactContent) { // Create a new issue in repo, return the issue id for later: creating the project card linked to this issue const issue = await createIssue(owner, repo, inactiveLists); - const issueId = issue.id; const issueNumber = issue.number; - // Get project id, in order to get the column id of `New Issue Approval` in `Project Board` - const projectId = await getProjectId(owner, repo); - // Get column id, in order to create a project card in `Project Board` and place in `New Issue Approval` - const columnId = await getColumnId(projectId); - // Create the project card, which links to the issue created in createIssue() above - await createProjectCard(issueId, columnId); + // Add issue number used to reference the issue and comment on the `Dev/PM Agenda and Notes` - const commentBody = `**Review Inactive Team Members:** #` + issueNumber; + const commentBody = `**Review Inactive Team Members:** #` + issueNumber + inactiveWithOpen; await postComment(agendaIssueNum, commentBody, github, context); } @@ -49,8 +47,8 @@ const createIssue = async (owner, repo, inactiveLists) => { per_page: 1, page: 1, }); - let thisIssueNumber = thisIssuePredict['data'][0]['number'] + 1 - + let thisIssueNumber = thisIssuePredict['data'][0]['number'] + 1; + // Uses issueTemplateParser to pull the relevant data from the issue template const pathway = 'github-actions/trigger-schedule/list-inactive-members/inactive-members.md'; const issueObject = issueTemplateParser(pathway); @@ -59,7 +57,7 @@ const createIssue = async (owner, repo, inactiveLists) => { let labels = issueObject['labels']; let milestone = parseInt(issueObject['milestone']); let body = issueObject['body']; - + // Replace variables in issue template body body = body.replace('${notifiedList}', notifiedList); body = body.replace('${removedList}', removedList); @@ -74,41 +72,20 @@ const createIssue = async (owner, repo, inactiveLists) => { labels, milestone, }); + console.log('Created issue ' + thisIssueNumber); return issue.data; }; -const getProjectId = async (owner, repo) => { - // Get all projects for the repo - let projects = await github.rest.projects.listForRepo({ - owner, - repo, - }); - // Select project with name `Project Board` then access the project `id` - let projectId = projects.data.filter((project) => { - return (project.name = "Project Board"); - })[0].id; - return projectId; -}; - -const getColumnId = async (projectId) => { - // Get all columns in the project board - let columns = await github.rest.projects.listColumns({ - project_id: projectId, - }); - // Select column with name `New Issue Approval` then access the column `id` - let columnId = columns.data.filter((column) => { - return column.name === "New Issue Approval"; - })[0].id; - return columnId; -}; - -const createProjectCard = async (issueId, columnId) => { - const card = await github.rest.projects.createCard({ - column_id: columnId, - content_id: issueId, - content_type: "Issue", - }); - return card.data; +const parseInactiveOpen = (inactiveOpens) => { + if(Object.keys(inactiveOpens).length === 0){ + return ''; + } else { + let inactiveOpen = '\r\n\nInactive members with open issues:\r\n'; + for(const [key, value] of Object.entries(inactiveOpens)){ + inactiveOpen += ' - ' + key + ': #' + value + '\r\n'; + } + return inactiveOpen; + } }; module.exports = main; diff --git a/github-actions/trigger-schedule/list-inactive-members/get-contributors-data.js b/github-actions/trigger-schedule/list-inactive-members/get-contributors-data.js new file mode 100644 index 0000000000..ed92ec4389 --- /dev/null +++ b/github-actions/trigger-schedule/list-inactive-members/get-contributors-data.js @@ -0,0 +1,185 @@ +// Import modules +const getTimeline = require('../../utils/get-timeline'); +const getTeamMembers = require('../../utils/get-team-members'); + +// Global variables +var github; +var context; + +const maintTeam = 'website-maintain'; +const botMembers = ['elizabethhonest', 'hfla-website-checklist', 'HackforLABot']; + +// Set date limits: we are sorting inactive members into groups to notify after 1 month and remove after 2 months. +// Since the teams take off December and July, the Jan. 1st and Aug. 1st runs are skipped (via `schedule-monthly.yml`). +// The Feb. 1st and Sept. 1st runs account for skipped months: 'oneMonth' & 'twoMonths' = 1 & 3 months respectively +let today = new Date(); +let twoMonths = (today.getMonth() === 1 || today.getMonth() === 8) ? 3 : 2; + +let oneMonthAgo = new Date(); // oneMonthAgo instantiated with date of "today" +oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); // then set oneMonthAgo from "today" +oneMonthAgo = oneMonthAgo.toISOString(); +let twoMonthsAgo = new Date(); // twoMonthsAgo instantiated with date of "today" +twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - twoMonths); // then set twoMonthsAgo from "today" +twoMonthsAgo = twoMonthsAgo.toISOString(); +let dates = [oneMonthAgo, twoMonthsAgo]; + + + +/** + * Main function + * @param {Object} g - github object from actions/github-script + * @param {Object} c - context object from actions/github-script + * @return {Object} results - object to use in `trim-inactive-members.js` + */ +async function main({ g, c }) { + github = g; + context = c; + + const [contributorsOneMonthAgo, contributorsTwoMonthsAgo, inactiveWithOpenIssue] = await fetchContributors(dates); + console.log(`-`.repeat(60)); + console.log('List of active contributors since ' + dates[0].slice(0, 10) + ':'); + console.log(contributorsOneMonthAgo); + + return { + recentContributors: contributorsOneMonthAgo, + previousContributors: contributorsTwoMonthsAgo, + inactiveWithOpenIssue: inactiveWithOpenIssue, + dates: dates, + }; +}; + + + +/** + * Function to fetch list of contributors with comments/commits/issues since date + * @returns {Object} allContributorsSinceOneMonthAgo - List of active contributors since oneMonthAgo + * @returns {Object} allContributorsSinceTwoMonthsAgo - List of active contributors since twoMonthsAgo + */ +async function fetchContributors(dates){ + let allContributorsSinceOneMonthAgo = {}; + let allContributorsSinceTwoMonthsAgo = {}; + let inactiveWithOpenIssue = {}; + + // Members of 'website-maintain' team are considered permanent members + const permanentMembers = await getTeamMembers(github, context, maintTeam); + + // Fetch all contributors with commit, comment, and issue (assignee) contributions + const APIs = [ + 'GET /repos/{owner}/{repo}/commits', // Gets list of member commits for dates + 'GET /repos/{owner}/{repo}/issues/comments', // Gets list of member comments for dates + 'GET /repos/{owner}/{repo}/issues' // Gets list of member assignments for dates + ]; + + for (const date of dates){ + const allContributorsSince = {}; + for(const api of APIs){ + let pageNum = 1; + let result = []; + + // Since Github only allows to fetch max 100 items per request, we need to 'flip' pages + while(true){ + // Fetch 100 items per each page (`pageNum`) + const contributors = await github.request(api, { + owner: context.repo.owner, + repo: context.repo.repo, + since: date, + per_page: 100, + page: pageNum + }); + + // If the API call returns an empty array, break out of loop- there is no additional data. + // Else if data is returned, push it to `result` and increase the page number (`pageNum`) + if(!contributors.data.length){ + break; + } else { + result = result.concat(contributors.data); + pageNum++; + } + } + + // Once we have looked at all pages and collected all the data, we create key-value pairs of recent contributors and store + // them in the `allContributorsSince` object. The contributor data that comes back from each API are stored differently, + // i.e. `author.login` vs `user.login` vs `assignee.login`. We want to extract the contributors' usernames for each situation. + for(const contributorInfo of result){ + // Check if username is stored in `author.login` + if(contributorInfo.author){ + allContributorsSince[contributorInfo.author.login] = true; + } + + // Check for usernames in `user.login`, but only include `created_at` time, and skip `user.login` b/c covered by 3rd API + else if(contributorInfo.user && contributorInfo.created_at > date && api != 'GET /repos/{owner}/{repo}/issues'){ + allContributorsSince[contributorInfo.user.login] = true; + } + // This check is done for `/issues` (3rd) API. Sometimes a user who created an issue is not the same as the + // assignee on that issue- we want to make sure that we count all assignees as active contributors as well. + // We only want to run this check if the assignee is not counted as an active contributor yet. + else if((contributorInfo.assignee) && (contributorInfo.assignee.login in allContributorsSince === false)){ + const issueNum = contributorInfo.number; + const timeline = await getTimeline(issueNum, github, context); + const assignee = contributorInfo.assignee.login; + const responseObject = await isEventOutdated(date, timeline, assignee); + // If timeline is not outdated, add member to `allContributorsSince` + if(responseObject.result === false){ + allContributorsSince[assignee] = true; + } + + // If timeline is more than two months ago, add to open issues with inactive. If issue title + // includes "Skills Issue" or "Pre-work Checklist", set flag to true, otherwise set to false + else if (date === dates[1]) { + const regex = /Pre-work checklist|Skills Issue/i; + if (regex.test(contributorInfo.title)) { + inactiveWithOpenIssue[assignee] = [issueNum, true]; + } else { + inactiveWithOpenIssue[assignee] = [issueNum, false]; + } + } + } + } + } + // Add permanent members from 'website-maintain' team to list of active contributors + for(let permanentMember in permanentMembers){ + allContributorsSince[permanentMember] = true; + } + // Add members of botMembers team to list of active contributors + for(let i = 0; i < botMembers.length; i++){ + allContributorsSince[botMembers[i]] = true; + } + + if(date === dates[0]){ + allContributorsSinceOneMonthAgo = allContributorsSince; + } else { + allContributorsSinceTwoMonthsAgo = allContributorsSince; + } + } + return [allContributorsSinceOneMonthAgo, allContributorsSinceTwoMonthsAgo, inactiveWithOpenIssue]; +} + + + +/** + * Helper function for fetchContributors() + * @param {String} date - date: oneMonthAgo, twoMonthsAgo + * @param {Object} timeline - object issue event timeline + * @param (String} assignee - member assigned to issue + * @returns {Boolean} true/false - whether event occurred after date + */ +function isEventOutdated(date, timeline, assignee) { + let lastAssignedTimestamp = null; + for (let i = timeline.length - 1; i >= 0; i--) { + let eventObj = timeline[i]; + let eventType = eventObj.event; + let eventTimestamp = eventObj.updated_at || eventObj.created_at; + + // update the lastAssignedTimestamp if this is the last (most recent) time an assignee was assigned to the issue + if (!lastAssignedTimestamp && eventType === 'assigned' && assignee === (eventObj.assignee.login)) { + lastAssignedTimestamp = eventTimestamp; + } + } + // If the assignee was assigned later than the 'date', the issue is not outdated so return false + if (lastAssignedTimestamp && (lastAssignedTimestamp >= date)) { + return { result: false }; + } + return { result: true }; +} + +module.exports = main; diff --git a/github-actions/trigger-schedule/list-inactive-members/inactive-members.md b/github-actions/trigger-schedule/list-inactive-members/inactive-members.md index 2dcafe8700..02efe8f359 100644 --- a/github-actions/trigger-schedule/list-inactive-members/inactive-members.md +++ b/github-actions/trigger-schedule/list-inactive-members/inactive-members.md @@ -22,8 +22,9 @@ The bot is checking for the following activity: - If you are assigned to an issue, that you have provided an update on the issue in the past 30 days. The updates are due weekly. - If your issue is a `Draft` in the "New Issue Approval" column, that you have added to it within the last 30 days. - If you are reviewing PRs, that you have posted a review comment within the past 30 days. +- If you are newly onboarded, that you are assigned to your "Skills Issue" and you have cloned the HfLA website repo to your personal repo. -If you have been inactive in the last 30 days (using the above measurements), you can become active again by doing at least one of the above actions. The bot will automatically remove you from next month's list. +If you have been inactive in the last 30 days (using the above measurements), you can become active again by doing at least one of the above actions. If you do not do at least one of the above actions, the bot will automatically remove you from the 'website-write' team in the next 30 days. ### Did we make a mistake? If you were active during the last 30 days (using the above measurements) and the bot made a mistake, let us know: Copy the following message into a comment below, add the pertinent issue or PR number, then select "Comment". Next, select "...", then "Reference in a new issue". [Watch demo](https://github.com/t-will-gillis/website/assets/40799239/59d45792-6950-46f0-a310-7c1ecd0c87be) diff --git a/github-actions/trigger-schedule/list-inactive-members/trim-inactive-members.js b/github-actions/trigger-schedule/list-inactive-members/trim-inactive-members.js new file mode 100644 index 0000000000..57be88d3fd --- /dev/null +++ b/github-actions/trigger-schedule/list-inactive-members/trim-inactive-members.js @@ -0,0 +1,219 @@ +// Import modules +const fs = require('fs'); +const getTeamMembers = require('../../utils/get-team-members'); +const addTeamMember = require('../../utils/add-team-member'); + +// Global variables +var github; +var context; + +const baseTeam = 'website'; +const writeTeam = 'website-write'; +const mergeTeam = 'website-merge'; + + + +/** + * Takes results of `get-contributors-data.js` for finding all contributors active in the periods since the dates + * of oneMonthAgo and twoMonthsAgo. Team members with no activity are removed as 'Inactive', with activity within + * twoMonthsAgo but not oneMonthAgo are notified, and with activity within the last month are 'Active' + * @param {Object} g - github object from actions/github-script + * @param {Object} c - context object from actions/github-script + * @param {Object} recentContributors - recentContributors since the dates[0] = recent cutoff + * @param {Object} previousContributors - previousContributors since the dates[1] = previous cutoff + * @param {Object} inactiveWithOpenIssue - Inactive contributors that have open issues + * @param {Object} dates - [recent, previous] dates of oneMonthAgo, twoMonthsAgo + */ +async function main({ g, c }, { recentContributors, previousContributors, inactiveWithOpenIssue, dates }) { + github = g; + context = c; + + const currentTeamMembers = await getTeamMembers(github, context, writeTeam); + console.log(`-`.repeat(60)); + console.log('Current members of ' + writeTeam + ':'); + console.log(currentTeamMembers); + + const [removedContributors, cannotRemoveYet] = await removeInactiveMembers(previousContributors, inactiveWithOpenIssue, currentTeamMembers); + console.log(`-`.repeat(60)); + console.log('Removed members from ' + writeTeam + ' inactive since ' + dates[1].slice(0, 10) + ':'); + console.log(removedContributors); + + console.log(`-`.repeat(60)); + console.log('Members inactive since ' + dates[1].slice(0, 10) + ' with open issues preventing removal:'); + console.log(cannotRemoveYet); + + // Repeat getTeamMembers() after removedContributors to compare with recentContributors + const updatedTeamMembers = await getTeamMembers(github, context, writeTeam); + const notifiedContributors = await notifyInactiveMembers(updatedTeamMembers, recentContributors); + console.log(`-`.repeat(60)); + console.log('Notified members from ' + writeTeam + ' inactive since ' + dates[0].slice(0, 10) + ':'); + console.log(notifiedContributors); + + writeData(removedContributors, notifiedContributors, cannotRemoveYet); +}; + + + +/** + * Remove contributors that were last active **before** the previous (twoMonthsAgo) date + * @param {Object} previousContributors - List of contributors active since previous date + * @param {Object} inactiveWithOpenIssue - Inactive members with open issues + * @returns {Array} removedMembers - List of members that were removed + * @returns {Object} cannotRemoveYet - List of members that cannot be removed due to open issues + */ +async function removeInactiveMembers(previousContributors, inactiveWithOpenIssue, currentTeamMembers){ + const removedMembers = []; + const cannotRemoveYet = {}; + const previouslyNotified = await readPreviousNotifyList(); + + // Loop over team members and remove them from the team if they are not in previousContributors list + for(const username in currentTeamMembers){ + if (!previousContributors[username]){ + // Prior to deletion, confirm that member is on the baseTeam + await addTeamMember(github, context, baseTeam, username); + // But if member has an open issue or was not on the previouslyNotified list, do not remove yet + if(username in inactiveWithOpenIssue && inactiveWithOpenIssue[username][1] === false){ + cannotRemoveYet[username] = inactiveWithOpenIssue[username][0]; + } else if((previouslyNotified.length > 0) && !(previouslyNotified.includes(username))){ + console.log('Member was not on last month\'s \'Inactive Members\' list, do not remove: ' + username); + } else { + // Remove member from all teams (except baseTeam) + const teams = [writeTeam, mergeTeam]; + for(const team of teams){ + // https://docs.github.com/en/rest/teams/members?apiVersion=2022-11-28#remove-team-membership-for-a-user + await github.request('DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}', { + org: context.repo.owner, + team_slug: team, + username: username, + }); + } + removedMembers.push(username); + // After removal, close member's "Skills Issue", if open + if(username in inactiveWithOpenIssue && inactiveWithOpenIssue[username][1] === true){ + closePrework(username, inactiveWithOpenIssue[username][0]); + } + } + } + } + return [removedMembers, cannotRemoveYet]; +} + + + +/** + * Function to close a just-removed inactive member's "Skills Issue", if open, and add a comment + * @param {String} member - name of member whose "Skills Issue" will be closed + * @param {Number} issueNum - number of member's "Skills Issue" + */ +async function closePrework(member, issueNum){ + // https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#update-an-issue + await github.request('PATCH /repos/{owner}/{repo}/issues/{issue_number}', { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNum, + state: 'closed' + }); + console.log(`Closing "Skills Issue" issue number ${issueNum} for ${member}`); + // https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#create-an-issue-comment + await github.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNum, + body: 'The Hack for LA Bot has closed this issue due to member inactivity.' + }); +} + + +/** + * Returns list of contributors that were not removed for inactivity, but who were last active **before** recent date + * @param {Array} updatedTeamMembers - List of updated team members + * @param {Array} recentContributors - List of contributors active since recent date (since OneMonthAgo) + * @returns {Array} notifiedMembers - List of members to be notified (that they are on the list to be removed) + */ +async function notifyInactiveMembers(updatedTeamMembers, recentContributors){ + const notifiedMembers = []; + + // Loop over team members and add to notifiedMembers list if they are not in recentContributors + for(const username in updatedTeamMembers){ + if (!recentContributors[username]){ + // Check whether member should be added to notifiedMembers list + if(await checkMemberIsNotNew(username)){ + notifiedMembers.push(username) + } + } + } + return notifiedMembers; +} + + + +/** + * Function to check if any of a member's 10 most recent repos match "description":"Hack for LA's Website" with "created_at" less + * than 30 days. If so, they are new members and should be excluded from removal or notification since they might be setting up still + * @param {String} member - Member's username + * @returns {Boolean} - True if member is not new, False if member is new + */ +async function checkMemberIsNotNew(member){ + + try { + const memberRepoResults = await github.request('GET /users/{username}/repos', { + username: member, + direction: 'asc', + sort: 'created', + per_page: 10, + }); + for(const memberRepo of memberRepoResults.data){ + if(memberRepo.description === "Hack for LA's website" && memberRepo.created_at > dates[0]){ + console.log("Member created organization repo within last month: " + member); + return false; + } + } + } catch {} + + // Else this member is not new and should be notified or removed from team as appropriate + return true; +} + + + +/** + * Function to find the previous month's "Review Inactive Team Members" issue and extract the raw notified members list + * @returns {Array} notifiedMembers - list of notified members from prev. month + */ + async function readPreviousNotifyList(){ + + try { + // Retrieve previous month's inactive member list + const filepath = 'github-actions/utils/_data/inactive-members.json'; + const rawData = fs.readFileSync(filepath, 'utf8'); + const parsedData = JSON.parse(rawData); + const notifiedMembers = parsedData['notifiedContributors']; + + return notifiedMembers; + + } catch (err) { + throw new Error(err); + } +} + + + +/** + * Function to save inactive members list to local repo for use in next job + * @param {Array} removedContributors - List of contributors that were removed + * @param {Array} notifiedContributors - List of contributors to be notified + * @param {Array} cannotRemoveYet - List of contributors that can't be removed yet + */ +function writeData(removedContributors, notifiedContributors, cannotRemoveYet){ + + const filepath = 'github-actions/utils/_data/inactive-members.json'; + const inactiveMemberLists = { removedContributors, notifiedContributors, cannotRemoveYet }; + + fs.writeFile(filepath, JSON.stringify(inactiveMemberLists, null, 2), (err) => { + if (err) throw err; + console.log(`-`.repeat(60)); + console.log("File `inactive-members.json` saved successfully!"); + }); +} + +module.exports = main; diff --git a/github-actions/utils/_data/inactive-members.json b/github-actions/utils/_data/inactive-members.json new file mode 100644 index 0000000000..3caeeb4655 --- /dev/null +++ b/github-actions/utils/_data/inactive-members.json @@ -0,0 +1,74 @@ +{ + "removedContributors": [ + "naveentata", + "moazDev1", + "joooseph2", + "muninnhugin", + "sakibian", + "hussainmudassir", + "notSayam", + "robertnjenga", + "zkamenov", + "jhong94", + "cchrizzle", + "alabador", + "Anahisv23", + "hkhaung", + "luisitocanlas", + "blaycoder", + "Limeload", + "eyaaoo", + "juanramirezwebdev", + "NPriyaK", + "Hsan2022", + "del9ra", + "andyphancode", + "siddharthpvaghela", + "j-m-rodriguez", + "colin-macrae", + "taylorbeee", + "AniC12", + "itazurakozo", + "saiteja-siddana", + "Rajwinder35" + ], + "notifiedContributors": [ + "jchue", + "marioantonini", + "ajb176", + "mayankt153", + "partapparam", + "DexinJ", + "mktr4n", + "mimiwrp", + "kunal-nsamant", + "pranjaliseth", + "jennisung", + "chrjl", + "TheManTheMythTheGameDev", + "nssensalo", + "vanessasinam", + "MarcosG119", + "irais-valenzuela", + "elliot-d-kim", + "Beatriz-G", + "gdkoo", + "purna-madala", + "DeniseLewis1", + "piecanoe", + "danvgar", + "Ayrh1", + "CreslinDev", + "freaky4wrld", + "mSharifHub", + "aidenjlee4321", + "williamzhang73", + "deepak-getpu", + "melissam640", + "elsong86", + "jmarinit" + ], + "cannotRemoveYet": { + "MarcosG119": 6266 + } +} \ No newline at end of file diff --git a/github-actions/utils/_data/label-directory.json b/github-actions/utils/_data/label-directory.json new file mode 100644 index 0000000000..4c3c18a392 --- /dev/null +++ b/github-actions/utils/_data/label-directory.json @@ -0,0 +1,830 @@ +{ + "addedToDevPmAgenda": [ + "Added to dev/pm agenda", + 6486982879 + ], + "automation": [ + "automation", + 3124741366 + ], + "awayOnHold": [ + "away on hold", + 7059625064 + ], + "bug": [ + "Bug", + 905516645 + ], + "complexity0": [ + "Complexity: Prework", + 5285254623 + ], + "complexity1": [ + "good first issue", + 905516649 + ], + "complexity2": [ + "Complexity: Small", + 3114700588 + ], + "complexity3": [ + "Complexity: Medium", + 2183123073 + ], + "complexity4": [ + "Complexity: Large", + 2183123843 + ], + "complexity5": [ + "Complexity: Extra Large", + 5821106740 + ], + "complexityIssueMaking": [ + "Complexity: See issue making label", + 5560490898 + ], + "complexityMissing": [ + "Complexity: Missing", + 6143851722 + ], + "dependencies": [ + "Dependencies", + 2024990162 + ], + "dependency": [ + "Dependency", + 2821418359 + ], + "discussion": [ + "Discussion", + 905516651 + ], + "documentation": [ + "documentation", + 1657305265 + ], + "draft": [ + "Draft", + 4117816871 + ], + "enhancement": [ + "enhancement", + 905516647 + ], + "epic": [ + "epic", + 3701919972 + ], + "er": [ + "ER", + 5945870612 + ], + "featureAPI": [ + "Feature: API", + 5359381713 + ], + "featureAccessibility": [ + "Feature: Accessibility", + 2862570817 + ], + "featureAdministrative": [ + "Feature: Administrative", + 1133688293 + ], + "featureAgenda": [ + "feature: agenda", + 4530619125 + ], + "featureAnalytics": [ + "Feature: Analytics", + 2366209158 + ], + "featureBoardGithubMaintenance": [ + "Feature: Board/GitHub Maintenance", + 3102736081 + ], + "featureCodeAlerts": [ + "Feature: Code Alerts", + 5771509385 + ], + "featureCodeOfConduct": [ + "feature: code of conduct", + 5274374779 + ], + "featureDesignSystem": [ + "Feature: Design system", + 3102710482 + ], + "featureDevEnv": [ + "feature: dev env", + 5621313099 + ], + "featureDocker": [ + "Feature: Docker", + 4746422764 + ], + "featureFeatureBranch": [ + "Feature: Feature Branch", + 3199371752 + ], + "featureGoogleAppsScripts": [ + "Feature: Google Apps Scripts", + 3570602420 + ], + "featureInfrastructure": [ + "Feature: Infrastructure", + 3121123661 + ], + "featureIssuesDashboard": [ + "feature: Issues Dashboard", + 6803394033 + ], + "featureMissing": [ + "Feature Missing", + 3102463671 + ], + "featureOnboardingContributingMd": [ + "Feature: Onboarding/Contributing.md", + 3102714248 + ], + "featureRecruitment": [ + "feature: recruitment", + 7082847252 + ], + "featureRefactorCss": [ + "Feature: Refactor CSS", + 2828575126 + ], + "featureRefactorGha": [ + "Feature: Refactor GHA", + 3325750543 + ], + "featureRefactorHtml": [ + "Feature: Refactor HTML", + 3326035014 + ], + "featureRefactorJsLiquid": [ + "Feature: Refactor JS / Liquid", + 2828567147 + ], + "featureResearch": [ + "feature: research", + 4303486825 + ], + "featureResearchPlan": [ + "feature: research plan", + 3624584466 + ], + "featureSkillsProductivityLadderDashboard": [ + "feature: skills / productivity ladder dashboard", + 5741577002 + ], + "featureSpelling": [ + "feature: spelling", + 6058643106 + ], + "featureStakeholderUpdates": [ + "feature: stakeholder updates", + 3538084405 + ], + "featureStandards": [ + "Feature: Standards", + 3102600868 + ], + "featureSurvey": [ + "feature: Survey", + 3959568333 + ], + "featureTables": [ + "Feature: Tables", + 3220448178 + ], + "featureTestLabel2": [ + "feature: test label 2", + 6808197695 + ], + "featureTimeCardDashboard": [ + "feature: time card dashboard", + 6822861537 + ], + "featureVideoResearch": [ + "Feature: Video Research", + 3967424932 + ], + "featureWiki": [ + "Feature: Wiki", + 2831478416 + ], + "frequencyMonthly": [ + "frequency: monthly", + 5302570770 + ], + "frequencyWeekly": [ + "frequency: weekly", + 5290510237 + ], + "fun": [ + "Fun", + 3199443790 + ], + "ghaNewProjectBoardCompatible": [ + "GHA New Project Board compatible", + 7094260634 + ], + "githubActions": [ + "github_actions", + 5546889221 + ], + "hacktoberfest": [ + "Hacktoberfest", + 3448025325 + ], + "hacktoberfestAccepted": [ + "hacktoberfest-accepted", + 3448050531 + ], + "hacktoberfestWithdrawn": [ + "hacktoberfest-withdrawn", + 3922320155 + ], + "hold": [ + "HOLD", + 1331569891 + ], + "ignoreAccidentallyClicked": [ + "Ignore: Accidentally clicked circle next to a box", + 6518297028 + ], + "ignoreDemo": [ + "Ignore: Demo", + 3828681807 + ], + "ignoreDuplicate": [ + "Ignore: Duplicate", + 3828519154 + ], + "ignoreNoLongerAProblem": [ + "Ignore: No longer a problem", + 4009101143 + ], + "ignoreNoLongerPlanned": [ + "Ignore: No longer planned", + 4755008074 + ], + "ignoreTest": [ + "Ignore: Test", + 3828519967 + ], + "issueIncomplete": [ + "Issue Incomplete", + 3166577659 + ], + "issueMakingLevel1": [ + "Issue Making: Level 1", + 5369116573 + ], + "issueMakingLevel2": [ + "Issue Making: Level 2", + 5369121177 + ], + "issueMakingLevel3": [ + "Issue Making: Level 3", + 7038941664 + ], + "issueMakingLevel4": [ + "Issue Making: Level 4", + 5369126992 + ], + "issueMakingLevel5": [ + "Issue Making: Level 5", + 5369129964 + ], + "javascript": [ + "javascript", + 5546889566 + ], + "manualDependencyRelease": [ + "manual dependency release", + 7057441869 + ], + "missingDependency": [ + "dependency missing", + 3220881612 + ], + "needMoreInfoToReleaseToBacklogIcebox": [ + "need more info to release to backlog/icebox", + 3336282261 + ], + "neededNextIssue": [ + "needed next issue", + 6557619824 + ], + "needsIssueLarge": [ + "needs issue: large", + 7059811275 + ], + "needsIssueMedium": [ + "needs issue: medium", + 6625428982 + ], + "newWinSubmission": [ + "new-win-submission", + 3033486479 + ], + "pFeature404Page": [ + "P-Feature: 404 page", + 3102711588 + ], + "pFeatureAboutUs": [ + "P-Feature: About Us", + 2565187521 + ], + "pFeatureCitizenEngagement": [ + "P-Feature: Citizen Engagement", + 3674884283 + ], + "pFeatureCivicTechInfrastructure": [ + "p-feature: Civic Tech Infrastructure", + 7057021625 + ], + "pFeatureCommunitiesOfPractice": [ + "P-Feature: Communities of Practice", + 3159585813 + ], + "pFeatureContactFormsWUsabilityResearch": [ + "P-Feature: Contact forms w usability research", + 3199705316 + ], + "pFeatureContributors": [ + "P-Feature: Contributors", + 3102829686 + ], + "pFeatureCredit": [ + "P-Feature: Credit", + 3079651481 + ], + "pFeatureDashboard": [ + "P-Feature: Dashboard", + 3826571464 + ], + "pFeatureDEI": [ + "p-feature: Diversity Equity and Inclusion", + 7057024001 + ], + "pFeatureDonate": [ + "P-Feature: Donate", + 3102797861 + ], + "pFeatureEnvironment": [ + "p-feature: Environment", + 7057024531 + ], + "pFeatureEvents": [ + "P-Feature: Events", + 2831320100 + ], + "pFeatureFooter": [ + "P-Feature: Footer", + 3272311289 + ], + "pFeatureGettingStarted": [ + "P-Feature: Getting Started", + 3080466385 + ], + "pFeatureHomePage": [ + "P-Feature: Home page", + 3079714479 + ], + "pFeatureImpact": [ + "P-Feature: Impact", + 3102857073 + ], + "pFeatureJoinPage": [ + "P-Feature: Join Page", + 2850627979 + ], + "pFeatureJustice": [ + "p-feature: Justice", + 7057025217 + ], + "pFeatureMemberProfile": [ + "p-feature: member profile", + 5250905300 + ], + "pFeatureMobile": [ + "p-Feature: Mobile", + 3602876103 + ], + "pFeatureNavigation": [ + "P-Feature: Navigation", + 3102742923 + ], + "pFeatureOpenRoles": [ + "feature: Open roles", + 3070145412 + ], + "pFeatureOrganizationalPage": [ + "P-Feature: Organizational Page", + 2465754188 + ], + "pFeaturePrivacyPolicy": [ + "P-Feature: Privacy Policy", + 3253969125 + ], + "pFeatureProgramArea": [ + "P-Feature: Program Area", + 2580708924 + ], + "pFeatureProjectInfoAndPage": [ + "P-Feature: Project Info and Page", + 2366205866 + ], + "pFeatureProjectMeetings": [ + "P-Feature: Project Meetings", + 3357903694 + ], + "pFeatureProjectsCheck": [ + "p-feature: Projects-check", + 5302503821 + ], + "pFeatureProjectsPage": [ + "P-Feature: Projects page", + 3272306602 + ], + "pFeatureRelatedCollateral": [ + "P-Feature: Related Collateral", + 9999999999 + ], + "pFeatureSDGs": [ + "p-feature: SDGs", + 5299505540 + ], + "pFeatureSdgPage": [ + "p-Feature: SDG page", + 4122353832 + ], + "pFeatureSitemap": [ + "P-Feature: Sitemap", + 3102717811 + ], + "pFeatureSocialSafetyNet": [ + "p-feature: Social Safety Net", + 7057025711 + ], + "pFeatureToolkit": [ + "P-Feature: Toolkit", + 2366198591 + ], + "pFeatureVoteRepresentation": [ + "p-feature: Vote Representation", + 7057026082 + ], + "pFeatureWinsPage": [ + "P-Feature: Wins Page", + 2831463428 + ], + "pFeatureWorkforceDevelopment": [ + "p-feature: Workforce Development", + 7057026444 + ], + "readyForDesignLead": [ + "ready for design lead", + 4102689482 + ], + "readyForDevLead": [ + "ready for dev lead", + 3391966124 + ], + "readyForIssueMaking": [ + "ready for issue making", + 6063987106 + ], + "readyForMergeTeam": [ + "ready for merge team", + 6888618481 + ], + "readyForOrgRep": [ + "ready for org rep", + 4795203011 + ], + "readyForPM": [ + "ready for product", + 4717543553 + ], + "readyForPrioritization": [ + "Ready for Prioritization", + 3247867138 + ], + "readyForResearchLead": [ + "ready for research lead", + 4496986970 + ], + "readyForStakeholder": [ + "ready for stakeholder", + 6092638824 + ], + "research": [ + "Research", + 1370325500 + ], + "researchRP001": [ + "Research: RP001", + 4314748126 + ], + "researchRP002": [ + "Research: RP002", + 4314742023 + ], + "researchRP003": [ + "Research: RP003", + 4314743630 + ], + "researchRP004": [ + "Research: RP004", + 4314744236 + ], + "researchRP005": [ + "Research: RP005", + 4314745134 + ], + "researchRP006": [ + "Research: RP006", + 4314745902 + ], + "researchRP007": [ + "Research: RP007", + 4314746817 + ], + "researchRP008": [ + "Research: RP008", + 4334676596 + ], + "researchRP009": [ + "Research: RP009", + 4334677039 + ], + "researchRP010": [ + "Research: RP010", + 4334677359 + ], + "researchRP011": [ + "Research: RP011", + 4334677804 + ], + "researchRP012": [ + "Research: RP012", + 4985272692 + ], + "researchRP013": [ + "Research: RP013", + 4985273825 + ], + "researchRP014": [ + "Research: RP014", + 4552555544 + ], + "roleBA": [ + "role: BA", + 3936089437 + ], + "roleBackEndDevOps": [ + "role: back end/devOps", + 2017367077 + ], + "roleDataAnalyst": [ + "role: data analyst", + 5240022852 + ], + "roleDesign": [ + "role: design", + 3080796365 + ], + "roleDesignLead": [ + "role: design lead", + 5083122470 + ], + "roleDevLeads": [ + "role: dev leads", + 3922864250 + ], + "roleFrontEnd": [ + "role: front end", + 1905598014 + ], + "roleHflaLeadership": [ + "role: hfla leadership", + 2634952026 + ], + "roleInfrastructure": [ + "role: infrastructure", + 1881810850 + ], + "roleLegal": [ + "role: legal", + 3253982725 + ], + "roleMergeTeam": [ + "role: merge team", + 7322859148 + ], + "roleMissing": [ + "role missing", + 6143849680 + ], + "roleOrgRep": [ + "role: Org Rep", + 5502327225 + ], + "roleProduct": [ + "role: product", + 1881080655 + ], + "roleQA": [ + "role: QA", + 7316991005 + ], + "roleResearchLead": [ + "role: Research Lead", + 4317739596 + ], + "roleTechnicalWriter": [ + "role: technical writer", + 5298500481 + ], + "roleUserResearch": [ + "role: user research", + 3146547561 + ], + "roleWriting": [ + "role: writing", + 2017474078 + ], + "sCTJ": [ + "s: CTJ", + 5226786717 + ], + "sHackforlaOrg": [ + "s: hackforla.org", + 5226786070 + ], + "sVRMS": [ + "s: VRMS", + 5226787543 + ], + "size025pt": [ + "size: 0.25pt", + 4512959732 + ], + "size05pt": [ + "size: 0.5pt", + 3692064969 + ], + "size13Pt": [ + "size: 13+pt", + 3683345363 + ], + "size1pt": [ + "size: 1pt", + 3683332441 + ], + "size2pt": [ + "size: 2pt", + 3683341683 + ], + "size3pt": [ + "size: 3pt", + 3683343324 + ], + "size5pt": [ + "size: 5pt", + 3683344186 + ], + "size8pt": [ + "size: 8pt", + 3683344760 + ], + "sizeMissing": [ + "size: missing", + 3191786859 + ], + "sizeNotCounted": [ + "size: not counted", + 3815894574 + ], + "skillAddedImageToCodebase": [ + "Skill: added image to codebase", + 6713302427 + ], + "skillEditYmlFile": [ + "Skill: edit YML file", + 6713310053 + ], + "stAddingAssets": [ + "ST: adding assets", + 6713278617 + ], + "stBranching": [ + "ST: branching", + 6713281975 + ], + "stYMLFile": [ + "ST: YML file", + 6713291595 + ], + "statusHelpWanted": [ + "Status: Help Wanted", + 905516648 + ], + "statusInactive1": [ + "To Update !", + 2731965789 + ], + "statusInactive2": [ + "2 weeks inactive", + 3278535433 + ], + "statusMissing": [ + "status: missing", + 6921032330 + ], + "statusUpdated": [ + "Status: Updated", + 2731966414 + ], + "statusUrgent": [ + "Status: Urgent", + 1353632485 + ], + "timeSensitive": [ + "time sensitive", + 2619153276 + ], + "transferToVRMS": [ + "Transfer to VRMS", + 3305512731 + ], + "uatHasVisuals": [ + "UAT: has visuals", + 3347092066 + ], + "uatNoVisuals": [ + "UAT: no visuals", + 3347092598 + ], + "updatedWithSkillsTemplate": [ + "Skills Template status: UPDATED", + 7379521201 + ], + "userAcceptanceTesting": [ + "User Acceptance Testing", + 2731962497 + ], + "waitingOnStakeholder": [ + "waiting on stakeholder", + 4867040794 + ], + "wontFix": [ + "wontfix", + 905516652 + ], + "NEW-labelForTestingOnly": [ + "Label for TESTING only!!!", + 9999999999 + ], + "NEW-labelForTestingPart2": [ + "Label for TESTING part 2", + 9999999999 + ], + "NEW-featureRoadmap": [ + "feature: Roadmap", + 7472857782 + ], + "NEW-pFeatureAccomplishments": [ + "p-feature: accomplishments", + 7505751413 + ], + "NEW-roleProject": [ + "role: project", + 7581729078 + ], + "NEW-driveSharedWithMe": [ + "drive: shared with me", + 7657270641 + ], + "NEW-featureBranding": [ + "feature: branding", + 7657357703 + ], + "NEW-milestoneMissing": [ + "milestone: missing", + 7695414022 + ], + "NEW-frontEnd": [ + "front end", + 9999999999 + ], + "NEW-roleFrontEndBackEnd": [ + "role: front-end/back-end", + 9999999999 + ] +} \ No newline at end of file diff --git a/github-actions/utils/_data/status-field-ids.js b/github-actions/utils/_data/status-field-ids.js new file mode 100644 index 0000000000..101532db3a --- /dev/null +++ b/github-actions/utils/_data/status-field-ids.js @@ -0,0 +1,86 @@ +/** + * The purpose of this utility is to list the (non-changing) GraphQL ids of the 'Status' fields + * for the Website Project so that functions will not need to run a GraphQL query when needed + * SEE BELOW for GraphQL query used to generate this list + * + * @params {String} statusField - Standardized name of status field (see lines 10-27) + * @returns {String} statusId - the field id of the selected status + */ + +function statusFieldIds(statusField) { + + const statusValues = new Map([ + ["Agendas", "864392c1"], + ["Ice_Box", "2b49cbab"], + ["Emergent_Requests", "d468e876"], + ["New_Issue_Approval", "83187325"], + ["Prioritized_Backlog", "434304a8"], + ["ERs_And_Epics_Ready", "c81aac49"], + ["In_Progress", "9a878e9c"], + ["Questions_In_Review", "53b56f8d"], + ["QA", "d013db69"], + ["UAT", "8fa184b4"], + ["QA_Senior_Review", "dcf54222"], + ["Done", "f8ad2dcb"], + ["Development_Team_Meeting", "68334e89"], + ["PR_Needs_Review", "e6140194"], + ["PR_Pending_Approval", "b8ef8e27"], + ["PR_Approved", "70e431d8"], + ["Feature_Branch", "88d8c3d6"], + ["IGNORE", "0728afac"], + ]); + + const statusId = statusValues.get(statusField); + + return statusId; +} + +/* +query findStatusSubfieldIds ($login: String!, $projNum: Int!, $fieldName: String!) { + organization(login: $login) { + projectV2(number: $projNum) { + id + field(name:$fieldName) { + ... on ProjectV2SingleSelectField { + id options{ + id + name + ... on ProjectV2SingleSelectFieldOption { + id + } + } + } + } + } + } +} + +{ + "login":"hackforla", + "projNum": 86, + "fieldName": "Status" +} +*/ + +/* +const Agendas = "Agendas"; +const Ice_Box = "Ice box"; +const Emergent_Requests = "Emergent Requests"; +const New_Issue_Approval = "New Issue Approval"; +const Prioritized_Backlog = "Prioritized backlog"; +const ERs_And_Epics = "ERs and epics that are ready to be turned into issues"; +const In_Progress = "In progress (actively working)"; +const Questions_In_Review = "Questions / In Review"; +const QA = "QA"; +const UAT = "UAT"; +const QA_Senior_Review = "QA - senior review"; +const Done = "Done"; +const Development_Team = "Development team meeting discussion items 🤔"; +const PR_Needs_Review = "PR Needs review (Automated Column, do not place items here manually)"; +const PR_Pending_Approval = "test-pending-approval (Automated Column, do not place items here manually)"; +const PR_Approved = "test-approved-by-reviewer (Automated Column, do not place items here manually)"; +const Feature_Branch = "Feature Branch - don't merge into gh-pages branch yet"; +const IGNORE = "IGNORE: PRs closed without being merged"; +*/ + +module.exports = statusFieldIds; diff --git a/github-actions/utils/add-team-member.js b/github-actions/utils/add-team-member.js new file mode 100644 index 0000000000..860001aa5f --- /dev/null +++ b/github-actions/utils/add-team-member.js @@ -0,0 +1,27 @@ +/** + * Function to return list of current team members + * @param {Object} github - github object from actions/github-script + * @param {Object} context - context object from actions/github-script + * @param {String} team - team to check for member + * @param {String} username - member to check for team membership + */ +async function addTeamMember(github, context, team, username){ + + const baseMember = await github.request('GET /orgs/{org}/teams/{team_slug}/memberships/{username}', { + org: context.repo.owner, + team_slug: team, + username: username, + }); + // If response status is not 200, need to add member to baseTeam + if(baseMember.status != 200){ + await github.request('PUT /orgs/{org}/teams/{team_slug}/memberships/{username}', { + org: context.repo.owner, + team_slug: team, + username: username, + role: 'member', + }); + console.log('Member added to \'' + team + '\' team: ' + username); + } +} + +module.exports = addTeamMember; diff --git a/github-actions/utils/check-team-membership.js b/github-actions/utils/check-team-membership.js new file mode 100644 index 0000000000..8b8d057197 --- /dev/null +++ b/github-actions/utils/check-team-membership.js @@ -0,0 +1,33 @@ +/** +* @param {octokit} github - Octokit object used to access GitHub API +* @param {String} githubUsername - The GitHub username of the user whose membership is to be checked. +* @param {String} team - The HFLA team the username's membership is checked against. Example: 'website-write' + +- Returns true or false depending on whether the username is found on the passed team, 404 means the user passed wasn't +found on the team passed. Any other type of error will be thrown. +- Need read:org permission to use this function, the least permissive token which contains this is the TEAMS token. +Lack of permission will result in a 403 error. +- The method of obtaining the GitHub username will vary depending on the contents of the context object. See GitHub action +docs on printing context information into the log. +*/ + +async function isMemberOfTeam(github, githubUsername, team) +{ + try { + await github.rest.teams.getMembershipForUserInOrg({ + org : 'hackforla', + team_slug : team, + username : githubUsername + }); + return true; + } catch (verificationError) { + if (verificationError.status == 404) { + return false; + } + else { + throw verificationError; + } + } +} + +module.exports = isMemberOfTeam; diff --git a/github-actions/utils/find-linked-issue.js b/github-actions/utils/find-linked-issue.js index b8e04d5e2b..3700ce2e6f 100644 --- a/github-actions/utils/find-linked-issue.js +++ b/github-actions/utils/find-linked-issue.js @@ -1,23 +1,35 @@ +/** + * Function that returns the number of a linked issue (if exists) + * @param {String} text - the text to search for keywords + * @returns - issueNumber, or false + */ function findLinkedIssue(text) { // Create RegEx for capturing KEYWORD #ISSUE-NUMBER syntax (i.e. resolves #1234) - const KEYWORDS = ['close', 'closes', 'closed', 'fix', 'fixes', 'fixed', 'resolve', 'resolves', 'resolved'] - let reArr = [] + const KEYWORDS = ['close', 'closes', 'closed', 'fix', 'fixes', 'fixed', 'resolve', 'resolves', 'resolved']; + let reArr = []; for (const word of KEYWORDS) { - reArr.push(`[\\n|\\s|^]${word} #\\d+\\s|^${word} #\\d+\\s|\\s${word} #\\d+$|^${word} #\\d+$`) + reArr.push(`[\\n|\\s|^]${word} #\\d+\\s|^${word} #\\d+\\s|\\s${word} #\\d+$|^${word} #\\d+$`); } // Receive and unpack matches into an Array of Array objs - let re = new RegExp(reArr.join('|'), 'gi') - let matches = text.matchAll(re) - matches = [...matches] - - // If only one match is found, return the issue number. Else return false. Also console.log results. + let re = new RegExp(reArr.join('|'), 'gi'); + let matches = []; + + // Find matches or throw error + try { + matches = text.matchAll(re); + matches = [...matches]; + } catch (err) { + console.error(err); + } + + // If only one match is found, return the issue number if (matches.length == 1) { - const issueNumber = matches[0][0].match(/\d+/) - return issueNumber[0] + const issueNumber = matches[0][0].match(/\d+/); + return issueNumber[0]; } else { - return null + return false; } } -module.exports = findLinkedIssue \ No newline at end of file +module.exports = findLinkedIssue; diff --git a/github-actions/utils/get-team-members.js b/github-actions/utils/get-team-members.js new file mode 100644 index 0000000000..cfcb997353 --- /dev/null +++ b/github-actions/utils/get-team-members.js @@ -0,0 +1,35 @@ +/** + * Function to return list of current team members + * @param {Object} github - github object from actions/github-script + * @param {Object} context - context object from actions/github-script + * @param {String} team - team from which to get member list + * @returns {Array} allMembers - Current team members + */ +async function getTeamMembers(github, context, team) { + let pageNum = 1; + let teamResults = []; + + // Get all members of team. Note: if total members exceed 100, we need to 'flip' pages + while (true) { + // https://docs.github.com/en/rest/teams/members?apiVersion=2022-11-28#list-team-members + const teamMembers = await github.request('GET /orgs/{org}/teams/{team_slug}/members', { + org: context.repo.owner, + team_slug: team, + per_page: 100, + page: pageNum, + }); + if (!teamMembers.data.length) { + break; + } else { + teamResults = teamResults.concat(teamMembers.data); + pageNum++; + } + } + const allMembers = {}; + for (const member of teamResults) { + allMembers[member.login] = true; + } + return allMembers; +} + +module.exports = getTeamMembers; diff --git a/github-actions/utils/get-timeline.js b/github-actions/utils/get-timeline.js index bb11e33929..b34cf410a7 100644 --- a/github-actions/utils/get-timeline.js +++ b/github-actions/utils/get-timeline.js @@ -1,34 +1,35 @@ /** - * Function that returns the timeline of an issue. - * @param {Number} issueNum the issue's number - * @returns an Array of Objects containing the issue's timeline of events + * Function that returns the timeline of an issue + * @param {Object} github - github object from actions/github-script + * @param {Object} context - context object from actions/github-script + * @param {Number} issueNum - the issue number + * @returns {Object} timelineArray - an array containing the timeline of issue events */ async function getTimeline(issueNum, github, context) { - let arra = [] - let page = 1 - while (true) { - try { - const results = await github.rest.issues.listEventsForTimeline({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: issueNum, - per_page: 100, - page: page, - }); - if (results.data.length) { - arra = arra.concat(results.data); - } else { - break - } - } catch (err) { - console.log(error); - continue - } - finally { - page++ + let timelineArray = []; + let page = 1; + while (true) { + try { + const results = await github.rest.issues.listEventsForTimeline({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNum, + per_page: 100, + page: page, + }); + if (results.data.length) { + timelineArray = timelineArray.concat(results.data); + } else { + break; } + } catch (err) { + console.log(err); + continue; + } finally { + page++; } - return arra } + return timelineArray; +} - module.exports = getTimeline; \ No newline at end of file +module.exports = getTimeline; diff --git a/github-actions/utils/hide-issue-comment.js b/github-actions/utils/hide-issue-comment.js new file mode 100644 index 0000000000..5eec7be841 --- /dev/null +++ b/github-actions/utils/hide-issue-comment.js @@ -0,0 +1,29 @@ +/** + * Minimize issue comment as OUTDATED given the comment's node Id + * @param {String} nodeId - node Id of comment to be marked as 'OUTDATED' + * + */ +async function minimizeIssueComment(github, nodeId) { + + const mutation = `mutation($nodeId: ID!) { + minimizeComment(input: {classifier: OUTDATED, subjectId: $nodeId}) { + clientMutationId + minimizedComment { + isMinimized + minimizedReason + } + } + }`; + + const variables = { + nodeId: nodeId, + }; + + try { + await github.graphql(mutation, variables); + } catch (error) { + throw new Error(`Error in minimizeIssueComment() function: ${error}`); + } +} + +module.exports = minimizeIssueComment; diff --git a/github-actions/utils/mutate-issue-status.js b/github-actions/utils/mutate-issue-status.js new file mode 100644 index 0000000000..5e4f335ff3 --- /dev/null +++ b/github-actions/utils/mutate-issue-status.js @@ -0,0 +1,46 @@ +/** + * Changes the 'Status' of an issue (with the corresponding itemId) to a newStatusValue + * @param {String} itemId - GraphQL item Id for the issue + * @param {String} newStatusValue - GraphQL Id value of the 'Status' field that the issue is moving to + * + */ +async function mutateIssueStatus( + github, + context, + itemId, + newStatusValue +) { + // Defaults for HfLA Website Project 86 + const WEBSITE_PROJECT_ID = 'PVT_kwDOALGKNs4Ajuck'; + const STATUS_FIELD_ID = 'PVTSSF_lADOALGKNs4AjuckzgcCutQ'; + + const mutation = `mutation($projectId: ID!, $fieldId: ID!, $itemId: ID!, $value: String!) { + updateProjectV2ItemFieldValue(input: { + projectId: $projectId, + fieldId: $fieldId, + itemId: $itemId, + value: { + singleSelectOptionId: $value + } + }) { + projectV2Item { + id + } + } + }`; + + const variables = { + projectId: WEBSITE_PROJECT_ID, + fieldId: STATUS_FIELD_ID, + itemId: itemId, + value: newStatusValue, + }; + + try { + await github.graphql(mutation, variables); + } catch (error) { + throw new Error('Error in mutateItemStatus() function: ' + error); + } +} + +module.exports = mutateIssueStatus; diff --git a/github-actions/utils/query-issue-info.js b/github-actions/utils/query-issue-info.js new file mode 100644 index 0000000000..c4242e7680 --- /dev/null +++ b/github-actions/utils/query-issue-info.js @@ -0,0 +1,58 @@ +/** + * @description - Get item info using its issue number + * @param {Object} github - GitHub object from function calling queryIssueInfo() + * @params {Object} context - Context of the function calling queryIssueInfo() + * @returns {Object} - An object containing the item ID and its status name + */ +async function queryIssueInfo(github, context, issueNum) { + const repoOwner = context.repo.owner; + const repoName = context.repo.repo; + + const query = `query($owner: String!, $repo: String!, $issueNum: Int!) { + repository(owner: $owner, name: $repo) { + issue(number: $issueNum) { + id + projectItems(first: 1) { + nodes { + id + fieldValues(first: 10) { + nodes { + ... on ProjectV2ItemFieldSingleSelectValue { + name + } + } + } + } + } + } + } + }`; + + const variables = { + owner: repoOwner, + repo: repoName, + issueNum: issueNum, + }; + + try { + const response = await github.graphql(query, variables); + + // Extract the list of project items associated with the issue + const projectData = response.repository.issue.projectItems.nodes; + + // Since there is always one item associated with the issue, + // directly get the item's ID from the first index + const id = projectData[0].id; + + // Iterate through the field values of the first project item + // and find the node that contains the 'name' property, then get its 'name' value + const statusName = projectData[0].fieldValues.nodes.find((item) => + item.hasOwnProperty("name")).name; + + return { id, statusName }; + } catch (error) { + throw new Error(`Error finding Issue #${issueNum} id and status; error = ${error}`); + } +} + +module.exports = queryIssueInfo; diff --git a/github-actions/utils/retrieve-label-directory.js b/github-actions/utils/retrieve-label-directory.js new file mode 100644 index 0000000000..2cb0383d9b --- /dev/null +++ b/github-actions/utils/retrieve-label-directory.js @@ -0,0 +1,34 @@ +// Import modules +const fs = require('fs'); + +// Global variables +var filepath = 'github-actions/utils/_data/label-directory.json'; +var labelData; + +/* + * Matches label reference name to the label display name from JSON + * @param {Array} labelKey - Key reference to look up display name + * @return {Array} labelName - Display name for each label + */ +function retrieveLabelName(labelKey) { + + // Retrieve label directory if not read already + if (labelData === undefined) { + console.log(`Reading label directory...`); + const rawData = fs.readFileSync(filepath, 'utf8'); + labelData = JSON.parse(rawData); + } + + let labelName = ''; + + try { + labelName = labelData[labelKey][0]; + console.log(`Success! Found labelKey: '${labelKey}', returning labelName: '${labelName}'`); + } catch (err) { + console.error(`Failed to find labelKey: '${labelKey}'`); + } + + return labelName; +} + +module.exports = retrieveLabelName; diff --git a/github-actions/utils/update-label-directory.js b/github-actions/utils/update-label-directory.js new file mode 100644 index 0000000000..6ada45692c --- /dev/null +++ b/github-actions/utils/update-label-directory.js @@ -0,0 +1,164 @@ +const fs = require('fs'); + +// Global variables +var filepath = 'github-actions/utils/_data/label-directory.json'; +var breakLine = `-`.repeat(60); +var github; +var context; + +/* + * Function triggered by the `update-label-directory.yml` that + * updates the "Label Object" in `label-directory.json` + * + * @param {Object} g - github object from actions/github-script + * @param {Object} c - context object from actions/github-script + * @returns {Object} + */ +async function main({ g, c }) { + + github = g; + context = c; + + var labelId = context.payload.label.id; + var labelName = context.payload.label.name; + var labelAction = context.payload.action; + let labelKey = ''; + let actionAddOn = ''; + let message = ''; + + // If label 'edited' but changes do not include 'name', label directory is not updated and workflow exits + if (labelAction === 'edited' && !context.payload.changes.name) { + console.log(`${breakLine}\n`); + console.log(`${labelName} label changed:`); + console.log(context.payload.changes); + console.log(`\n${breakLine}\n`); + labelAction = "no update"; + labelKey = "n/a"; + message = `Edit to description and/or color only, no updates to JSON or SoT`; + console.log(message); + return {labelAction, labelKey, labelName, labelId, message}; + } + + // Otherwise, retrieve label directory + var rawData = fs.readFileSync(filepath, 'utf8'); + var data = JSON.parse(rawData); + + // Initial information to log + console.log(`${breakLine}\n`); + console.log(`Label reference info:`); + console.log(context.payload.label); + console.log(`\n${breakLine}\n`); + + // If label 'deleted', check for 'labelId' in label directory and if found return 'labelKey' + if (labelAction === 'deleted') { + labelKey = cycleThroughDirectory(data, Number(labelId)); + if (labelKey) { + // If the 'labelKey' is found with 'labelId', replace 'labelId' with '9999999999' in JSON and flag for review + let prevId = labelId; + labelId = 9999999999; + message = `Found labelKey: ${labelKey} for labelName: ${labelName} using labelId: ${prevId} ---> ${labelId}. Id no longer valid. This needs review!`; + actionAddOn = ' / id found'; + console.log(message); + writeToJsonFile(data, labelKey, labelId, labelName); + } else { + // If the 'labelKey' not found with 'labelId', rerun with 'labelName' + labelKey = cycleThroughDirectory(data, labelName); + if (labelKey) { + message = `Found a labelKey: ${labelKey} for labelName: ${labelName}. However, this DOES NOT MATCH labelId: ${labelId}. No updates to JSON. This needs review!`; + console.log(message); + actionAddOn = ' / check name'; + } else { + message = `Found neither labelName: ${labelName} nor labelId: ${labelId}. No updates to JSON. This needs review!`; + console.log(message); + actionAddOn = ' / not found'; + } + } + } + + // If 'edited' check for 'labelId' in label directory and if found return 'labelKey' + if (labelAction === 'edited' ) { + let prevName = context.payload.changes.name.from; + labelKey = cycleThroughDirectory(data, Number(labelId)); + // If the 'labelKey' is returned, it is assumed that the change is known. Label directory will be updated w/ new 'name' + if (labelKey) { + message = `Found labelKey: ${labelKey} for labelName: ${prevName} ---> ${labelName} and labelId: ${labelId}.`; + actionAddOn = ' / found'; + } else { + // If the 'labelId' is not found, create a new 'labelKey' and flag this label edit for review + labelKey = createInitiallabelKey(data, labelName); + message = `Did not find labelKey: for labelName: ${labelName} using labelId: ${labelId}. Adding Label Object with new labelKey: ${labelKey}.`; + actionAddOn = ' / added'; + } + console.log(message); + writeToJsonFile(data, labelKey, labelId, labelName); + } + + // If 'created' then 'labelKey' won't exist, create new camelCased 'labelKey' so label entry can be added to directory + if (labelAction === 'created') { + labelKey = createInitiallabelKey(data, labelName); + message = `Created initial labelKey: ${labelKey} for new labelName: ${labelName} and new labelId: ${labelId}. Adding Label Object to JSON.`; + console.log(message); + writeToJsonFile(data, labelKey, labelId, labelName); + } + + // Final step is to return label data packet to workflow + console.log(`\nSending Label Object to Google Apps Script / Sheets file`); + labelAction += actionAddOn; + return { labelAction, labelKey, labelName, labelId, message }; +} + + + +/* + * HELPER FUNCTIONS for main() + * + */ +function cycleThroughDirectory(data, searchValue) { + let labelKey = ''; + for (let [key, value] of Object.entries(data)) { + if (value.includes(searchValue)) { + labelKey = key; + return labelKey; + } + } + return undefined; +} + + + +// If the label has not been created, prepend 'NEW-' to labelKey to flag it +function createInitiallabelKey(data, labelName) { + let labelKey = 'NEW-'; + const isAlphanumeric = str => /^[a-z0-9]+$/gi.test(str); + let labelInterim = labelName.split(/[^a-zA-Z0-9]+/); + for (let i = 0; i < labelInterim.length ; i++) { + if (i === 0) { + labelKey += labelInterim[0].toLowerCase(); + } else if (isAlphanumeric(labelInterim[i])) { + labelKey += labelInterim[i].split(' ').map((word) => word[0].toUpperCase() + word.slice(1).toLowerCase()).join(' '); + } + } + return labelKey; +} + + + +function writeToJsonFile(data, labelKey, labelId, labelName) { + try { + data[labelKey] = [labelName, Number(labelId)]; + console.log(`\nStaging Label Object to JSON:\n { "${labelKey}": [ "${labelName}", "${labelId}" ] }`); + } catch (error) { + console.log(error); + } + + // Write data file in prep for committing changes to label directory + fs.writeFile(filepath, JSON.stringify(data, null, 2), (err) => { + if (err) throw err; + console.log(`${breakLine}\n`); + console.log(`Changes to Label Directory JSON file have been staged. Next step will commit changes.`); + }); +} + + + +module.exports = main; diff --git a/google-apps-scripts/gh-requests/Code.js b/google-apps-scripts/gh-requests/Code.js index 2c14f52af2..2207666f78 100644 --- a/google-apps-scripts/gh-requests/Code.js +++ b/google-apps-scripts/gh-requests/Code.js @@ -12,19 +12,27 @@ const ACCEPT_HEADER = { /************************************************** FUNCTIONS USING THE FETCH REQUESTS ********************************************************************/ -// Retrieves a GitHub file's SHA -function getSHA(fileName) { +// Retrieves a GitHub file's SHA and associated wins (in JSON format) +function getWins(fileName) { const branch = "update-wins-data"; const url = `https://api.github.com/repos/elizabethhonest/website/contents/_data/external/${fileName}?ref=${branch}`; const response = getRequest_(url, ACCEPT_HEADER.Repository); if (response === false ) { console.log('SHA retrieval failed.') - return false; + return [null, null]; } + let decodedContent = JSON.parse(decode(response.body.content)); + console.log('SHA retrieved.') - return response.body.sha; + return [response.body.sha, decodedContent]; +} + +function testGetWins() { + const fileName = "_wins-data.json"; + const [sha, content] = getWins(fileName); + console.log(content.length); } // Updates Github File given a payload @@ -119,7 +127,8 @@ function setToken_() { } const doc = DocumentApp.openById(id); - documentProperties.setProperty('TOKEN', doc.getBody().getText()) + documentProperties.setProperty('TOKEN', doc.getBody().getText()); + console.log(documentProperties.getProperty(`TOKEN`)) } // Uses base64 to decode an input diff --git a/google-apps-scripts/wins-form-responses/Code.js b/google-apps-scripts/wins-form-responses/Code.js index e676a55b83..705333b44e 100644 --- a/google-apps-scripts/wins-form-responses/Code.js +++ b/google-apps-scripts/wins-form-responses/Code.js @@ -68,46 +68,34 @@ function main() { const cleanedAndFormattedKeyValueData = JSON.stringify(sortedKeyValueData, null, 5); const encodedKeyValueData = Utilities.base64Encode(`${cleanedAndFormattedKeyValueData}`, Utilities.Charset.UTF_8); - // Retrieves latest sha of the _wins data file, which is needed for edits later + // Retrieves latest sha and content of the _wins data file, which is needed for edits later const keyValueFile = "_wins-data.json" - const keyValueSha = ghrequests.getSHA(keyValueFile); + const [keyValueSha, keyValueContent] = ghrequests.getWins(keyValueFile); if (keyValueSha === false) { - console.log('Ending script...') + console.log('Ending script due to lack of returned SHA from getWins().'); return 1; } - const writeResponse = ghrequests.updateWinsFile(keyValueFile, encodedKeyValueData, keyValueSha); - if (writeResponse === false) { - console.log('Ending script...') - return 1; + // detect any changes to Wins-form (Responses) by comparing performing a string comparison + if (!arrEq(sortedKeyValueData, keyValueContent)) { + console.log("Entry difference detected. Updating wins file..."); + const writeResponse = ghrequests.updateWinsFile(keyValueFile, encodedKeyValueData, keyValueSha); + if (writeResponse === false) { + console.log('Ending script...') + return 1; + } } - - /* - ** This section deals with the array of data for wins-data.json - ** Eventually, lines 91-107 below should be deleted (EXCLUDING createPrResponse) when the team fully migrates from using wins-data.json to _wins-data.json - ** The payload is formatted and prepared for an API request to GitHub - */ - - // Create an array of data for wins-data.json - const cleanedAndFormattedArrayData = JSON.stringify(filteredRows); - // const encodedArrayData = Utilities.base64Encode(`${cleanedAndFormattedArrayData}`); - const encodedArrayData = Utilities.base64Encode(cleanedAndFormattedArrayData, Utilities.Charset.UTF_8); - - // Retrieves latest sha of the wins data file - const arrayFile = "wins-data.json" - const arrayDataSha = ghrequests.getSHA(arrayFile); - if (arrayDataSha === false) { + else { + console.log("No new entry difference detected."); console.log('Ending script...') return 1; } - const writeResponse2 = ghrequests.updateWinsFile(arrayFile, encodedArrayData, arrayDataSha); - if (writeResponse2 === false) { - console.log('Ending script...') - return 1; + function arrEq(arr1, arr2) { + return JSON.stringify(arr1) === JSON.stringify(arr2); } - const createPrResponse = ghrequests.createPR(); + ghrequests.createPR(); } /************************************************** TRIGGER("On Form Submit") 2 SECTION ********************************************************************/ @@ -254,7 +242,7 @@ function compareResponsesAndReview() { //Gets the values for(let i = 0; i <= 10; i++){ - values = reviewInfoSplit[i].split(" : "); + const values = reviewInfoSplit[i].split(" : "); let value = values[1]; if (value !== undefined) { value = value.trim(); @@ -284,7 +272,7 @@ function compareResponsesAndReview() { } if (responseValue !== reviewValues[j]) { - console.log("Mismatch found!\nResponse value: " + responseValue + "\nReview value: " + reviewValues[j]) + console.log("Mismatch found!\nResponse value: " + responseValue + "\nReview value: " + reviewValues[j]); unamatched++; } else { matched++; diff --git a/pages/communities-of-practice.html b/pages/communities-of-practice.html index 7a300e44b8..4446488df3 100644 --- a/pages/communities-of-practice.html +++ b/pages/communities-of-practice.html @@ -21,7 +21,7 @@

    Communities of Practice

    To join the Slack channels below, you first need to be a member of our Hack for LA Slack Community. If you have not joined yet, please follow the steps in Getting Started.

    - commmunity of practice header + community of practice header
    @@ -38,8 +38,7 @@

    {{ community[1].name}}

    {{ community[1].description}}

    Meeting Times: - {% if community[1].meeting-times %}{{ community[1].meeting-times }}{% else %}TBD{% endif %}
    -

    +

    Leadership Type: {% if community[1].leadership-type %}{{ community[1].leadership-type }}{% else %}TBD{% endif %} @@ -48,11 +47,11 @@

    {{ community[1].name}}

    {% for leader in community[1].leadership %}
    - + {% endif %} {% endfor %} -
    \ No newline at end of file + + \ No newline at end of file diff --git a/pages/events-check.html b/pages/events-check.html new file mode 100644 index 0000000000..27a2881714 --- /dev/null +++ b/pages/events-check.html @@ -0,0 +1,54 @@ +--- +layout: default +title: Events - Hack for LA +permalink: /events-check +--- + + + + + + +
    + {% include events-page/header-container-content.html %} +
    + +
    + +

    Our Events

    +
    +
    + {% include events-page/left-col-content.html %} +
    + +
    + {% include events-page/right-col-content-check.html%} +
    +
    + +

    + Our Locations +

    + +
    +
    +

    + In light of the COVID-19 pandemic, Hack for LA has suspended its in-person + events below. The organization remains fully active, and all events are + now being conducted remotely using Zoom at the days/times listed above. +

    +
    + +
    +

    + + See our Locations +

    +
    +
    + +
    + {% include events-page/our-locations-content.html %} +
    + +
    \ No newline at end of file diff --git a/pages/getting-started.html b/pages/getting-started.html index ae602991dd..6d5bffd6d9 100644 --- a/pages/getting-started.html +++ b/pages/getting-started.html @@ -98,7 +98,7 @@

    STEP 2: Join Your Communit
    -
  • Receive access to the Google Drive and Github repository by sending a Slack message of your Github username and Gmail address to a CoP lead. +
  • Receive access to the Google Drive and GitHub repository by sending a Slack message of your GitHub username and Gmail address to a CoP lead.

  • diff --git a/pages/index.html b/pages/index.html index 80ca215e0a..2619e4996c 100644 --- a/pages/index.html +++ b/pages/index.html @@ -4,7 +4,6 @@ {% assign remote-only = 'true' %} {% if remote-only == 'false' %} {%- include hero.html -%} - {%- include calendar.html -%} {%- include current-projects.html -%} {%- include press.html -%} {%- include about.html -%} diff --git a/pages/join-us.html b/pages/join-us.html index 0997cc085b..33025db598 100644 --- a/pages/join-us.html +++ b/pages/join-us.html @@ -40,7 +40,7 @@

    Advise Us

    1. Follow the steps on our Getting Started page
    2. - Connect with our leadership team on the #admin #admin channel
    diff --git a/pages/program-areas.html b/pages/program-areas.html index b3c6128ffa..a410b1eb9a 100644 --- a/pages/program-areas.html +++ b/pages/program-areas.html @@ -16,55 +16,50 @@

    Program Areas

    - {% assign sorted_program_areas = site.data.internal.program-areas | sort %} + {% assign sorted_program_areas = site.program-areas | sort %} {% for program_areas in sorted_program_areas %} - {% if program_areas[1].size > 0 %}
    - +
    -

    {{program_areas[1].name}}

    -

    {{program_areas[1].description}}

    +

    {{program_areas.name}}

    +

    {{program_areas.description}}

    SDGs: - {% if program_areas[1].SDG %} - {% for sdg in program_areas[1].SDG %} - {% if forloop.last == true %} - and {{sdg}} - {% else %} - {{sdg}}, - {% endif %} - {% endfor %} + {% if program_areas.SDG %} + {% for sdg in program_areas.SDG %} + {% if forloop.last == true %} + and {{sdg}} + {% else %} + {{sdg}}, + {% endif %} + {% endfor %} {% endif %}

      {% for project in site.projects %} - {% for project_program in project.program-area %} - {% if program_areas[1].program-area == project_program and project.visible %} - {% assign project_relative_path = project.slug | prepend: "../projects/" %} -
    • - - {{project.title}} -
    • - {% endif %} - {% endfor %} + {% for project_program in project.program-area %} + {% if program_areas.program-area == project_program and project.visible %} + {% assign project_relative_path = project.slug | prepend: "../projects/" %} +
    • + + {{project.title}} +
    • + {% endif %} + {% endfor %} {% endfor %}
    - -
    - - {% endif %} {% endfor %} -
    +