Local Development - liferesearchapp/life-research-members-portal GitHub Wiki

Requirements

  • Node.js (includes node package manager)
  • Any web browser

Recommended Environment

VS Code with the following extensions:

  • ESLint linter - this will give helpful warnings using the dev dependencies eslint and eslint-config-next already included in package.json.
  • Prettier code formatter - set this as your default formatter and enable format on save
  • Prisma syntax highlighting for prisma schema files
  • SCSS Intellisense Intellisense for SCSS files (code completion, hover tooltips, signature help)
  • CSS Variable Autocomplete Autocomplete for CSS variables like var(--volcano-5), useful for browsing colors from src/styles/_antd-colors.scss

Microsoft SQL Server (Developer) For creating a localhost server (See Prisma SQL Server on Windows (Local) for setup intructions). SQL Server Management Studio (SSMS) For editing the database.

A minimum of two desktop browsers and one mobile browser, for manual testing.

Recommended Documentation

Hosting Locally

1. Fork this repo, then clone it onto your own machine.

2. In the root directory of the application, run npm i to install dependencies.

3. Get the database connection string. In the Azure Portal you can find the connection string under the SQL database -> connection strings -> JDBC -> JDBC (SQL authentication). Just remove the "jdbc:" prefix and insert the database password.

4. Add a file named .env to the root directory that contains DATABASE_URL=<database connection string>.

Example .env file:

DATABASE_URL="sqlserver://life-server.database.windows.net:1433;database=life-database;user=chami033@life-server;password={your_password_here};encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;"

Localhost example:

DATABASE_URL_TEST="sqlserver://localhost:1433;database={your_test_database_name_here};integratedSecurity=true;trustServerCertificate=true;"

5. Localhost Testing Database Setup:

  • Insert at least 1 entry into tables: event_type, faculty, level, member_type, org_scope, org_type, product_type, source, status, target and topic (See Database for relations).
  • (Single-Institute Only) Insert a admin account entry into the account table.
  • (Multi-Institute Only) Insert a super admin account entry into the account table and the initial/first institute into the institute table. Establish membership between the two by adding a related entry into the member, memberInstitute and instituteAdmin (so that the "at least 1 admin per institute" condition is fulfilled, though super admins can self-assign to the admin role of the selected institute through their account profile) tables.

6. To run in development mode (automatic reloads on change): npm run dev

The app can be found at http://localhost:3000 in a web browser.

Optional: To test a production build:

npm run build

npm run start

Steps to Add a Feature

Some of these steps may not be necessary depending on the feature, and many steps can be done in different orders.

Database Modification

  1. Design new database relationships
  2. Add new relationships to the database schema via SSMS
  3. Pull the new schema using npx prisma db pull
  4. Generate the new Prisma client using npx prisma generate

Backend API Route

  1. Create the API route by adding a file to src/pages/api
  2. Add the API route to src/routing/api-routes
  3. Add a function that extracts the relevant data from the database using Prisma
  4. Export the return type and parameter types of the function (may be able to reuse the return type of another function)
  5. Export a default function that handles the HTTP request and checks the correct permissions

Frontend Service and Interface

  1. Add a service function under src/services that calls the new route, handles errors and notifications, and has the correct parameter and return type imported from the backend
  2. Add a new frontend page route under src/pages with appropriate auth guards if necessary
  3. Add the new route to src/routing/page-routes
  4. Add a way to navigate to the new page
  5. Add React components to the new page

Try to break it 🔨

Creating and Integrating a New Page

This will guide you through creating a new page and integrating it into the Portal. We will cover the following steps:

  1. Create a new page and its components
  2. Add the page to the navigation menu
  3. Create and organize components for the new module
  4. Add context providers and API routes

Create a new page and its components

To create a new page, follow these steps:

  • Under src/pages, create a folder with the name of the desired page and add an index.tsx file.

Example: For a grants page, create pages/grants/index.tsx that exports a React component:

const GrantsPage: NextPage = () => {
  return <AllGrants />;
};

export default GrantsPage;
  • Later on in that same folder, create a register.tsx file to add new items to the database, and an [id] folder to access either private or public profile of that same module.

  • API functions are defined in src/pages/api and handle HTTP requests and execute queries on the database. More details can be found in the backend documentation.

Add the page to the navigation menu

To access the new page in the navigation menu, edit src/components/navbar/nav-menu.tsx and add it to either generalItems for the public, registeredItems for registered users, or adminItems for admin only.

  • Example: To access grants in the navigation:
const generalItems = [
  { label: en ? "Grants" : "Subvention", href: PageRoutes.allGrants },
];

  • Navigate to src/routes/page-routes to add the corresponding page routes:
const PageRoutes = {
  allGrants: "/grants",
} as const;

Create and organize components for the new module

Create a folder in src/components for all the components that will be used for the new module. For example, see components/grants. Components are organized as shown in the table below:

Name File Description
AllGrants all-grants.tsx Displays a table of grants, with filters to filter the grants based on name, status and source
DeleteGrantButton delete-grant-button.tsx A button that opens a modal to delete a grant
PrivateGrantProfile grant-private-profile.tsx A detailed view of a private grant's profile
PublicGrantDescription grant-public-description.tsx Displays the public information of a grant in a table format
PublicGrantForm grant-public-form.tsx Displays a form for updating public information of a grant.
PublicGrantProfile grant-public-profile.tsx Displays the public grant profile information for a specific grant id.
RegisterGrant grant-register.tsx Provides a form for registering a grant

Filters are implemented in components/filters. Filters are components that provide a dropdown list for selecting multiple items. For example:

  • GrantNameFilter from "../filters/grant-name-filter";
  • GrantStatusFilter from "../filters/grant-status-filter";
  • GrantSourceFilter from "../filters/grant-source-filter";

Duplicate existing styles, and add the new styles in _globals.scss.

Add context providers and API routes

To add the corresponding context provider, navigate to services/context/. Context providers are used to store the list of the corresponding items and manage the state for loading, refreshing, and updating this information.

  • Example: { AllGrantsCtx } from "../../services/context/all-grants-ctx"; (it uses GrantPublicInfo and apiRoutes)'

Note that GrantPublicInfo is added to /services/_types, a service that imports all the required types from the API routes and uses NonNullable to remove nullability from the imported types.

apiRoutes are located in routing/api-routes.ts. This file defines a constant object ApiRoutes containing the URLs of all the API endpoints in the application. The URLs are stored as properties of the object. For example, ApiRoutes.allGrants is the URL for retrieving all grants.

With these steps, you should be able to create and integrate a new page into the Portal successfully. Remember to follow best practices for React and Next.js development and to organize your components and files in a modular manner.

Testing and debugging tips

Once you have completed the steps above, it's essential to test the new page and its components to ensure that they function as expected.

  • Run the development server with npm run dev or yarn dev.
  • Visit the new page in your browser by navigating to the corresponding URL (e.g., http://localhost:3000/grants for the grants page).
  • Verify that the components are rendering correctly and that the filters, forms, and other functionality are working as intended.
  • Test the new page and components with different user roles (public, registered user, admin) to ensure proper access control and functionality.

Debugging with Chrome

Chrome Developer Tools (also known as Chrome DevTools) is a powerful way to identify and fix issues in your web applications. Here's how you can debug using the Chrome console:

  • Open Chrome DevTools: Right-click on your web page and select "Inspect" or use the keyboard shortcut Ctrl + Shift + I (Windows/Linux) or Cmd + Option + I (Mac).
  • Navigate to the Console tab: In the DevTools window, click on the "Console" tab to access the console. Here, you can see logged messages, errors, and warnings.
  • Use console.log(): In your code, add console.log() statements to print out the values of variables, objects, or any other information that will help you understand the state of your application at various points.
  • Debug JavaScript: Navigate to the "Sources" tab in DevTools to debug your JavaScript code. You can set breakpoints, step through code execution, and inspect variables and their values. To set a breakpoint, click on the line number in the source code where you want to pause execution. You can also use the debugger; statement in your code to create a breakpoint programmatically.
  • Monitor network activity: Use the "Network" tab in DevTools to inspect network requests and responses. This can help you identify issues related to API calls, loading of resources, or other network-related issues.