Skip to content

Commit 4a5f51c

Browse files
authored
Merge branch 'development' into create-script-output-list-files-containing-linting-errors
2 parents 1d28cc3 + 3cd9d98 commit 4a5f51c

29 files changed

+1627
-523
lines changed

.github/workflows/pr-instructions.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
echo ${{ steps.instruction.outputs.result }} > addingPrInstructions/artifact/artifact.txt
2929
3030
- name: Upload Artifacts
31-
uses: actions/upload-artifact@v3
31+
uses: actions/upload-artifact@v4
3232
with:
3333
name: adding-pr-instructions-artifact
3434
path: addingPrInstructions/artifact/

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Note: Understanding how git remotes work will make collaborating much easier. Yo
106106

107107
### **2.3 Get up and running**
108108

109-
1. Install NVM (Node Version Manager). NVM allows you to easily manage and switch between multiple versions of Node.
109+
1. Install [NVM (Node Version Manager)](https://github.com/nvm-sh/nvm). NVM allows you to easily manage and switch between multiple versions of Node.
110110

111111
- Verify the installation: `nvm --version`
112112
- Once NVM is verified, run the following commands from the root of the project:

backend/controllers/project.controller.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,26 @@ ProjectController.bulkUpdateManagedByUsers = async function (req, res) {
130130
}
131131
};
132132

133+
// Update onboard/offboard visibility for a project
134+
ProjectController.updateOnboardOffboardVisibility = async function (req, res) {
135+
const { ProjectId } = req.params;
136+
const { onboardOffboardVisible } = req.body;
137+
138+
try {
139+
const project = await Project.findByIdAndUpdate(
140+
ProjectId,
141+
{ onboardOffboardVisible },
142+
{ new: true }
143+
);
144+
145+
if (!project) {
146+
return res.status(404).send({ message: 'Project not found' });
147+
}
148+
149+
return res.status(200).send(project);
150+
} catch (err) {
151+
return res.status(400).send({ message: 'Error updating visibility', error: err.message });
152+
}
153+
};
154+
133155
module.exports = ProjectController;

backend/models/project.model.js

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,51 @@ Idea for the future: programmingLanguages, numberGithubContributions (pull these
1616
*/
1717

1818
const projectSchema = mongoose.Schema({
19-
name: { type: String, trim: true },
20-
description: { type: String, trim: true },
21-
githubIdentifier: { type: String, trim: true },
22-
projectStatus: { type: String }, // Active, Completed, or Paused
23-
location: { type: String, trim: true }, // DTLA, Westside, South LA, or Remote (hacknight)
24-
//teamMembers: { type: String }, // commented since we should be able to get this from Project Team Members table
25-
createdDate: { type: Date, default: Date.now }, // date/time project was created
26-
completedDate: { type: Date }, // only if Status = Completed, date/time completed
27-
githubUrl: { type: String, trim: true }, // link to main repo
28-
slackUrl: { type: String, trim: true }, // link to Slack channel
29-
googleDriveUrl: { type: String, trim: true },
30-
googleDriveId: { type: String },
31-
hflaWebsiteUrl: { type: String, trim: true },
32-
videoConferenceLink: { type: String },
33-
lookingDescription: { type: String }, // narrative on what the project is looking for
34-
recruitingCategories: [{ type: String }], // same as global Skills picklist
35-
partners: [{ type: String }], // any third-party partners on the project, e.g. City of LA
36-
managedByUsers: [{ type: String }] // Which users may manage this project.
19+
name: { type: String, trim: true },
20+
description: { type: String, trim: true },
21+
githubIdentifier: { type: String, trim: true },
22+
projectStatus: { type: String }, // Active, Completed, or Paused
23+
location: { type: String, trim: true }, // DTLA, Westside, South LA, or Remote (hacknight)
24+
//teamMembers: { type: String }, // commented since we should be able to get this from Project Team Members table
25+
createdDate: { type: Date, default: Date.now }, // date/time project was created
26+
completedDate: { type: Date }, // only if Status = Completed, date/time completed
27+
githubUrl: { type: String, trim: true }, // link to main repo
28+
slackUrl: { type: String, trim: true }, // link to Slack channel
29+
googleDriveUrl: { type: String, trim: true },
30+
googleDriveId: { type: String },
31+
hflaWebsiteUrl: { type: String, trim: true },
32+
videoConferenceLink: { type: String },
33+
lookingDescription: { type: String }, // narrative on what the project is looking for
34+
recruitingCategories: [{ type: String }], // same as global Skills picklist
35+
partners: [{ type: String }], // any third-party partners on the project, e.g. City of LA
36+
managedByUsers: [{ type: String }], // Which users may manage this project.
37+
onboardOffboardVisible: { type: Boolean, default: true }, // Whether onboarding/offboarding forms are visible on the project page
3738
});
3839

39-
projectSchema.methods.serialize = function() {
40-
return {
41-
id: this._id,
42-
name: this.name,
43-
description: this.description,
44-
githubIdentifier: this.githubIdentifier,
45-
// owner: this.owner,
46-
projectStatus: this.projectStatus,
47-
location: this.location,
48-
//teamMembers: this.teamMembers,
49-
createdDate: this.createdDate,
50-
completedDate: this.completedDate,
51-
githubUrl: this.githubUrl,
52-
slackUrl: this.slackUrl,
53-
googleDriveUrl: this.googleDriveUrl,
54-
googleDriveId: this.googleDriveId,
55-
hflaWebsiteUrl: this.hflaWebsiteUrl,
56-
videoConferenceLink: this.videoConferenceLink,
57-
lookingDescription: this.lookingDescription,
58-
recruitingCategories: this.recruitingCategories,
59-
partners: this.partners,
60-
managedByUsers: this.managedByUsers
61-
};
40+
projectSchema.methods.serialize = function () {
41+
return {
42+
id: this._id,
43+
name: this.name,
44+
description: this.description,
45+
githubIdentifier: this.githubIdentifier,
46+
// owner: this.owner,
47+
projectStatus: this.projectStatus,
48+
location: this.location,
49+
//teamMembers: this.teamMembers,
50+
createdDate: this.createdDate,
51+
completedDate: this.completedDate,
52+
githubUrl: this.githubUrl,
53+
slackUrl: this.slackUrl,
54+
googleDriveUrl: this.googleDriveUrl,
55+
googleDriveId: this.googleDriveId,
56+
hflaWebsiteUrl: this.hflaWebsiteUrl,
57+
videoConferenceLink: this.videoConferenceLink,
58+
lookingDescription: this.lookingDescription,
59+
recruitingCategories: this.recruitingCategories,
60+
partners: this.partners,
61+
managedByUsers: this.managedByUsers,
62+
onboardOffboardVisible: this.onboardOffboardVisible,
63+
};
6264
};
6365

6466
const Project = mongoose.model('Project', projectSchema);

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"morgan": "^1.10.0",
5757
"node-cron": "^2.0.3",
5858
"node-fetch": "^2.6.7",
59-
"nodemailer": "^7.0.7"
59+
"nodemailer": "^7.0.11"
6060
},
6161
"directories": {
6262
"test": "test"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Mock the healthCheck controller
2+
jest.mock('../controllers/healthCheck.controller.js');
3+
4+
// Import the healthCheck router and controller
5+
const healthCheck = require('./healthCheck.router.js');
6+
const { HealthCheckController } = require('../controllers');
7+
8+
// Create a mock test server
9+
const express = require('express');
10+
const supertest = require('supertest');
11+
const testapp = express();
12+
testapp.use('/api/healthcheck', healthCheck);
13+
14+
// Set up mock request for the controller
15+
const request = supertest(testapp);
16+
17+
describe('Unit testing for Health Check Router', () => {
18+
// Clear all mocks after each test
19+
afterEach(() => {
20+
jest.clearAllMocks();
21+
});
22+
23+
describe('READ', () => {
24+
it('should return status code 200 and message "I\'m Alive" with GET /api/healthcheck', async (done) => {
25+
// Mock the controller method
26+
HealthCheckController.isAlive.mockImplementationOnce((req, res) => {
27+
res.status(200).send("I'm Alive!");
28+
});
29+
30+
// Call GET API endpoint
31+
const response = await request.get('/api/healthcheck');
32+
33+
// Test
34+
expect(HealthCheckController.isAlive).toHaveBeenCalled();
35+
expect(response.status).toBe(200);
36+
expect(response.text).toBe("I'm Alive!");
37+
38+
// Marks completion of the test
39+
done();
40+
});
41+
});
42+
});

backend/routers/projects.router.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ router.patch('/:ProjectId', AuthUtil.verifyCookie, ProjectController.updateManag
2222
// Bulk update for editing project members
2323
router.post('/bulk-updates', AuthUtil.verifyCookie, ProjectController.bulkUpdateManagedByUsers);
2424

25+
// Update onboard/offboard visibility for a project
26+
router.patch('/:ProjectId/visibility', AuthUtil.verifyCookie, ProjectController.updateOnboardOffboardVisibility);
27+
2528
module.exports = router;
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Delete Project Script - Modular Structure
2+
3+
This directory contains the modular implementation of the project deletion script.
4+
5+
## File Structure
6+
7+
```
8+
deleteProject/
9+
├── README.md # This file
10+
├── index.js # Main orchestration file (entry point)
11+
├── config.js # Configuration constants (database names)
12+
├── utils.js # Utility functions (validation, CLI parsing, help)
13+
├── finders.js # Database query functions (find related records)
14+
├── displays.js # Display functions (show detailed information)
15+
└── deleters.js # Deletion functions (delete/update operations)
16+
```
17+
18+
## Module Descriptions
19+
20+
### `index.js`
21+
22+
Main orchestration file that coordinates the entire deletion process.
23+
24+
- Parses command-line arguments
25+
- Validates input and environment
26+
- Connects to MongoDB
27+
- Orchestrates the find → display → delete workflow
28+
- Handles errors and cleanup
29+
30+
### `config.js`
31+
32+
Configuration constants used throughout the script.
33+
34+
- Database names (production, development, test)
35+
- Can be extended with other configuration values
36+
37+
### `utils.js`
38+
39+
Utility and helper functions.
40+
41+
- `checkEnv()` - Validates required environment variables
42+
- `isValidObjectId()` - Validates MongoDB ObjectId format
43+
- `getProjectIdFromArgs()` - Extracts project ID from CLI arguments
44+
- `printHelp()` - Displays usage information
45+
46+
### `finders.js`
47+
48+
Database query functions for finding related records.
49+
50+
- `findProject()` - Find the project by ID
51+
- `findProjectEvents()` - Find all events for the project
52+
- `findEventCheckIns()` - Find all check-ins for project events
53+
- `findProjectTeamMembers()` - Find team members
54+
- `findUsersReferencingProject()` - Find users with project references
55+
- `findRelatedRecurringEvents()` - Find recurring events
56+
57+
### `displays.js`
58+
59+
Display functions for showing detailed record information.
60+
61+
- `displayUserDetails()` - Show user information
62+
- `displayEventDetails()` - Show event information
63+
- `displayCheckInDetails()` - Show check-in information (with user lookup)
64+
- `displayProjectTeamMemberDetails()` - Show team member information
65+
- `displayRecurringEventDetails()` - Show recurring event information
66+
67+
### `deleters.js`
68+
69+
Deletion and update functions.
70+
71+
- `deleteCheckIns()` - Delete check-in records
72+
- `deleteProjectTeamMembers()` - Delete team member records
73+
- `updateUsersRemoveProject()` - Remove project references from users
74+
- `deleteEvents()` - Delete event records
75+
- `deleteRecurringEvents()` - Delete recurring event records
76+
- `deleteProject()` - Delete the project itself
77+
78+
## Usage
79+
80+
### From the deleteProject directory:
81+
82+
```bash
83+
node index.js --project-id=<PROJECT_ID> [options]
84+
```
85+
86+
### From the scripts directory (backwards compatible):
87+
88+
```bash
89+
node deleteProjectAndAssociatedRecords.js --project-id=<PROJECT_ID> [options]
90+
```
91+
92+
### Options:
93+
94+
- `--project-id=<ID>` - MongoDB ObjectId of the project to delete (REQUIRED)
95+
- `--prod` - Operate on production database
96+
- `--live` - Operate on development/staging database
97+
- `--test` - Operate on test database
98+
- `--mock` - Dry run (no actual deletion)
99+
- `--execute` - Execute the deletion
100+
- `--help` - Show help message
101+
102+
## Examples
103+
104+
```bash
105+
# Dry run on production
106+
node index.js --project-id=644748563212e6001fbca24a --prod --mock
107+
108+
# Execute on test database
109+
node index.js --project-id=644748563212e6001fbca24a --test --execute
110+
111+
# Execute on production (with 5-second warning)
112+
node index.js --project-id=644748563212e6001fbca24a --prod --execute
113+
```
114+
115+
## Safety Features
116+
117+
1. **Mock mode** - Preview all changes before executing
118+
2. **5-second warning** - Countdown for production/live databases
119+
3. **Validation** - Validates project ID and environment variables
120+
4. **Detailed output** - Shows exactly what will be deleted
121+
5. **Orphan detection** - Identifies orphaned check-ins
122+
123+
## Deletion Order
124+
125+
The script follows this order to maintain referential integrity:
126+
127+
1. Check-ins
128+
2. Project team members
129+
3. User references (updated, not deleted)
130+
4. Events
131+
5. Recurring events
132+
6. Project
133+
134+
## Environment Requirements
135+
136+
- `MIGRATION_DB_URI` - MongoDB connection string
137+
138+
Load from `backend/.env` file.
139+
140+
## See Also
141+
142+
- Main documentation: `tmp/GUIDE.md`
143+
- Manual deletion steps for MongoDB Compass users
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Configuration constants for project deletion script
3+
*/
4+
5+
// Database names
6+
const PROD_DB_NAME = 'db'; // Actual production database
7+
const DEV_DB_NAME = 'vrms-test'; // Development/staging database
8+
const DEV_TEST_DB_NAME = 'vrms-populate-projects-test'; // Test database for migration
9+
10+
module.exports = {
11+
PROD_DB_NAME,
12+
DEV_DB_NAME,
13+
DEV_TEST_DB_NAME,
14+
};

0 commit comments

Comments
 (0)