forked from flamingchickens1540/CLUCK
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
136 changed files
with
18,039 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
name: CI | ||
|
||
on: [push, pull_request] | ||
|
||
jobs: | ||
lint: | ||
name: 'Lint' | ||
runs-on: ubuntu-latest | ||
permissions: | ||
checks: write | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup Node | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: 21 | ||
cache: 'npm' | ||
- name: Install Node Dependencies | ||
run: npm ci | ||
|
||
# Linting | ||
- name: Create ESLint Report | ||
run: node_modules/.bin/eslint --output-file eslint_report.json --format json . | ||
continue-on-error: true | ||
- name: Annotate Code Linting Results | ||
uses: ataylorme/eslint-annotate-action@v3 | ||
continue-on-error: true | ||
with: | ||
report-json: 'eslint_report.json' | ||
- name: Run ESLint | ||
run: node_modules/.bin/eslint . | ||
|
||
build: | ||
name: 'Build' | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup Node | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: 21 | ||
cache: 'npm' | ||
- name: Install Node Dependencies | ||
run: npm ci | ||
# Build | ||
- name: Build | ||
run: npm run build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# dev | ||
.yarn/ | ||
!.yarn/releases | ||
.vscode/* | ||
!.vscode/launch.json | ||
!.vscode/*.code-snippets | ||
.idea/workspace.xml | ||
.idea/usage.statistics.xml | ||
.idea/shelf | ||
|
||
# deps | ||
node_modules/ | ||
|
||
# env | ||
.env | ||
.env.production | ||
|
||
# logs | ||
logs/ | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
# misc | ||
.DS_Store | ||
|
||
|
||
/config/*.* | ||
!/config/custom-environment-variables.json | ||
!/config/example.json | ||
/static/app.css | ||
_*.ts | ||
/.idea | ||
/public/ | ||
|
||
/dev/*.manifest.json | ||
/build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"trailingComma": "none", | ||
"bracketSpacing": true, | ||
"quoteProps": "consistent", | ||
"tabWidth": 4, | ||
"semi": false, | ||
"singleQuote": true, | ||
"printWidth": 1000, | ||
"overrides": [ | ||
{ | ||
"files": ["**/*.ts"], | ||
"options": { | ||
"printWidth": 180 | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Copyright (c) 2023 FRC Team 1540 | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Maintaining | ||
|
||
## Adding Members | ||
|
||
Visit `/admin/members/` and enter data in the bottom row. Slack IDs will automatically populate by the email | ||
|
||
## Adjusting Seasons | ||
|
||
Set the `start_date` field to the date you want to start tracking current hour information from, typically around kickoff or the end of summer. Any hour submissions after this point will be counted towards totals. It can be in any format accepted by the [Javascript Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date) | ||
|
||
## Refreshing Veracross photos | ||
|
||
Open [the student directory](https://portals.veracross.com/catlin/student/directory/1) and paste the following into the browser console. You may need to disable CSP to run this script. | ||
|
||
```js | ||
function loadNext() { | ||
console.log('loading more pages...') | ||
const elem = document.querySelector('.DirectoryEntries_LoadMoreEntriesButton') | ||
if (elem) { | ||
elem.click() | ||
setTimeout(loadNext, 1000) | ||
} else { | ||
const people = document.querySelectorAll('.directory-Entry_Header') | ||
const data = {} | ||
people.forEach((person) => { | ||
const email = person.querySelector('a')?.innerHTML?.trim() | ||
const photo = person.querySelector('.directory-Entry_PersonPhoto--full')?.src | ||
if (email && photo) { | ||
data[email] = photo | ||
} else { | ||
console.log('missing data for', person) | ||
} | ||
}) | ||
fetch('https://cluck.team1540.org/api/members/fallback_photos', { | ||
method: 'POST', | ||
headers: { 'X-Api-Key': 'YOUR-API-KEY' }, | ||
body: JSON.stringify(data) | ||
}) | ||
.then((resp) => resp.text()) | ||
.then(console.log) | ||
} | ||
} | ||
|
||
loadNext() | ||
``` | ||
## Adding Member Fields | ||
Additional fields not used by CLUCK can be added to the spreadsheet directly. See the [registered column](https://docs.google.com/spreadsheets/d/1p18eJW29CzLn-zZKBKm-OOM6BtR-oLlrZVfNJtNPl9A/edit?gid=568325748#gid=568325748&range=B2:B46) and ['extra' sheet](https://docs.google.com/spreadsheets/d/1p18eJW29CzLn-zZKBKm-OOM6BtR-oLlrZVfNJtNPl9A/edit?gid=2140052736#gid=2140052736) in the template spreadsheet for an example | ||
- Hours & Certs row 3 represents the table that the column is found in | ||
- Hours & Certs row 4 is the column name | ||
- Hours & Certs row 5 is automatically calculated to be the column index | ||
Make sure to update [the db model](prisma/schema.prisma), [the spreadsheet mapping](src/spreadsheet/index.ts), and the [member dashboard](src/views/admin_members) if adding new fields to CLUCK. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# CLUCK | ||
|
||
CLUCK is a team management tool designed by and for FRC Team 1540. It manages hour tracking and certifications, integrating with Slack and Google Sheets. | ||
|
||
## Installation | ||
|
||
See [SETUP.md](SETUP.md) for installation instructions. | ||
|
||
## Feature Showcase | ||
|
||
| Label | Image | | ||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| Spreadsheet | [![Spreadsheet](https://github.com/user-attachments/assets/1cbaee67-7ab1-4e45-9774-339cd8300b24)](https://docs.google.com/spreadsheets/d/1p18eJW29CzLn-zZKBKm-OOM6BtR-oLlrZVfNJtNPl9A/edit?gid=568325748#gid=568325748) | | ||
| Slack Time Logging | ![Slack](https://github.com/user-attachments/assets/80a61a51-43b1-4673-a483-513a408e6726) | | ||
| Slack User Info | ![Slack](https://github.com/user-attachments/assets/df06e2c2-933e-4472-a1c3-cf830798bffa) | | ||
| Member Dashboard | ![Dashboard](https://github.com/user-attachments/assets/3e1229ec-ecdf-44c8-9ab9-4ed958d4e78b) | | ||
| Certifications Dashboard | ![Certifications](https://github.com/user-attachments/assets/cdd3dbf4-bbce-4a3b-9463-8fe612d294e5) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Setup | ||
|
||
## Config | ||
|
||
Set the `start_date` field to the date you want to start tracking current hour information from. This should be the start of the current season, and is used to calculate which hour logs count towards totals. It can be in any format accepted by the [Javascript Date constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date) | ||
|
||
Make a copy of the `./config/example.json` file as `./config/yourenvlabel.json` and adjust the fields as needed. You will need to set the environment variable `NODE_ENV='yourenvlabel'` when running to load the correct config file | ||
|
||
Create a `.env` file in the base folder, and in it set the following DATABASE_URL variable for Prisma | ||
|
||
```bash | ||
DATABASE_URL="postgres://user@host/db" | ||
``` | ||
|
||
## Database | ||
|
||
Once you have a postgres database running, run the following to apply the Prisma schema | ||
|
||
```bash | ||
npx prisma migrate deploy | ||
``` | ||
|
||
Then, to populate the database with dummy data (for development), run `dev/seed_db.ts`. This will remove existing database records, do not use in production | ||
|
||
```bash | ||
tsx dev/seed_db.ts | ||
``` | ||
|
||
## Slack | ||
|
||
If you plan to run this in a workspace with other instances, you'll need to generate a manifest with different slash command names. First, set the `slack.app.command_prefix` field in your config file, then run the following to create the customized manifest: | ||
|
||
```bash | ||
tsx dev/generate_manifest.ts | ||
``` | ||
|
||
If your instance is the only one, you can use `dev/manifest.json` directly | ||
You'll need to [create a Slack application](https://api.slack.com/apps), which you should do from the app manifest you're using. | ||
|
||
- After you complete the setup flow, click "Install to Workspace" | ||
- `slack.app.signing_secret` can be found in Basic Information > App Credentials > Signing Secret | ||
- `slack.app.app_token` should be generated in Basic Information > App-Level Tokens with scope `connections:write` | ||
- `slack.app.bot_token` can be found in OAuth & Permissions > Bot User OAuth Token | ||
|
||
The slack user token needs to be authorized by an administrator, and requires the scopes shown in `dev/user_manifest.json`. You can either add these to the main app's manifest (if the main app will be authorized by a slack administrator) or create a separate app for the user token. The user token is used to set profile fields and usergroups by selected departments. | ||
`slack.app.user_token` can be left as an empty string if desired to disable the profile field and department usergroup functionality, otherwise it will appear next to where the bot token was after reauthorization. | ||
|
||
Make sure to also set the appropriate user and channel ids | ||
|
||
## Spreadsheet | ||
|
||
CLUCK is designed to work with a Google Sheets spreadsheet as a frontend. You can make a copy of the [template spreadsheet](https://docs.google.com/spreadsheets/d/1p18eJW29CzLn-zZKBKm-OOM6BtR-oLlrZVfNJtNPl9A/copy) and set the `google.sheet.id` field in your config file to the id in the URL. | ||
Then, to create the credentials, follow [Google's instructions to create a service account](https://developers.google.com/workspace/guides/create-credentials#service-account), and download the `credentials.json` file. Set the `google.account.private_key` and `google.account.client_email` entries in your config file to the matching keys in `credentials.json`. | ||
|
||
You'll need to share the spreadsheet with the email address in `client_email` as an editor to allow the bot to access it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"slack": { | ||
"app": { | ||
"signing_secret": "XXX", | ||
"bot_token": "xoxb-XXX", | ||
"app_token": "xapp-X-XXX", | ||
"user_token": "xoxp-XXX", | ||
"command_prefix": "" | ||
}, | ||
"profile": { | ||
"department": "XAAAAA", | ||
"certs": "XAAAA" | ||
}, | ||
"channels": { | ||
"celebration": "CXXXX", | ||
"void": "CXXX", | ||
"approval": "DXXX", | ||
"certification_approval": "DXXX" | ||
}, | ||
"groups": { | ||
"students": "SXXX" | ||
}, | ||
"users": { | ||
"admins": ["UXXX"] | ||
} | ||
}, | ||
"google": { | ||
"sheet_id": "", | ||
"account": { | ||
"private_key": "", | ||
"client_email": "" | ||
} | ||
}, | ||
"start_date": "2024-06-01", | ||
"port": 3000, | ||
"default_photo": "/static/img/default_member.webp" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import prod_manifest from './manifest.json' | ||
import fs from 'fs/promises' | ||
import config from '~config' | ||
|
||
const dev_manifest = structuredClone(prod_manifest) | ||
const prefix = config.slack.app.command_prefix | ||
if (prefix) { | ||
dev_manifest.features.slash_commands.forEach((cmd) => { | ||
cmd.command = '/' + prefix + '_' + cmd.command.slice(1) | ||
}) | ||
dev_manifest.display_information.name += ` (${prefix})` | ||
dev_manifest.features.bot_user.display_name += ` (${prefix})` | ||
} | ||
await fs.writeFile(`./dev/${prefix}.manifest.json`, JSON.stringify(dev_manifest, null, 4)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
{ | ||
"display_information": { | ||
"name": "CLUCK", | ||
"description": "A Bot for Logging Robotics Hours", | ||
"background_color": "#2b323d" | ||
}, | ||
"features": { | ||
"app_home": { | ||
"home_tab_enabled": true, | ||
"messages_tab_enabled": true, | ||
"messages_tab_read_only_enabled": false | ||
}, | ||
"bot_user": { | ||
"display_name": "Time Sheet", | ||
"always_online": true | ||
}, | ||
"shortcuts": [ | ||
{ | ||
"name": "Log Hours", | ||
"type": "global", | ||
"callback_id": "log_time", | ||
"description": "Opens interactive hours logging popup" | ||
} | ||
], | ||
"slash_commands": [ | ||
{ | ||
"command": "/log", | ||
"description": "Log Hours and Minutes", | ||
"usage_hint": "[hours]h [minutes]m [activity]", | ||
"should_escape": false | ||
}, | ||
{ | ||
"command": "/graph", | ||
"description": "Graphs hours for members", | ||
"usage_hint": "[@user]...", | ||
"should_escape": true | ||
}, | ||
{ | ||
"command": "/certify", | ||
"description": "[Manager Only] Give a user a certification", | ||
"should_escape": true | ||
}, | ||
{ | ||
"command": "/clearlogin", | ||
"description": "Logs you out, giving no hours", | ||
"should_escape": false | ||
}, | ||
{ | ||
"command": "/voidtime", | ||
"description": "[Copresident Only]", | ||
"usage_hint": "<user>", | ||
"should_escape": true | ||
}, | ||
{ | ||
"command": "/loggedin", | ||
"description": "Shows who is currently signed in", | ||
"should_escape": false | ||
}, | ||
{ | ||
"command": "/hours", | ||
"description": "Shows your current hour information", | ||
"should_escape": false | ||
}, | ||
{ | ||
"command": "/departments", | ||
"description": "Allows you to manage your department associations", | ||
"should_escape": false | ||
} | ||
] | ||
}, | ||
"oauth_config": { | ||
"scopes": { | ||
"bot": ["app_mentions:read", "channels:history", "channels:join", "channels:read", "chat:write", "chat:write.public", "commands", "files:write", "groups:read", "im:history", "im:read", "im:write", "mpim:read", "usergroups:read", "users:read", "users.profile:read", "users:read.email"] | ||
} | ||
}, | ||
"settings": { | ||
"event_subscriptions": { | ||
"bot_events": ["app_home_opened", "app_mention"] | ||
}, | ||
"org_deploy_enabled": false, | ||
"socket_mode_enabled": true, | ||
"token_rotation_enabled": false | ||
} | ||
} |
Oops, something went wrong.