6 minute read

The project manager is for management of projects which user can add, view, edit and delete (CRUD functions) a project. This project is used React, bootstrap and apollo client for a front-end, GraphQL, Node.js and express-graphql for a server side, Mongo DB for a DATA side.


Create a package.json file

To create a package.json, I need to run a command down below.

npm init -y

Install express, express-graphql, graphql, mongoose, cors and colors

npm i express express-graphql graphql mongoose cors colors

Install nodemon and dotenv

npm i -D nodemon dotenv

Explanation of each tool

  • express: Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

  • express-graphql: The express-graphql module provides a simple way to create an Express server that runs a GraphQL API.

  • graphql: GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.

  • mongoose: Mongoose is a JavaScript object-oriented programming library that creates a connection between MongoDB and the Express web application framework.

  • cors: CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.

  • colors: The Color node is a basic node that lets you change the color of your objects at any time in a non-destructive way. It only outputs color and does not have any inputs.

  • nodemon: nodemon is a tool that helps develop Node.js based applications by automatically restarting the node application when file changes in the directory are detected.

  • dotenv: Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env

Explanation for each line

const express = require("express");
  • require(‘express’): Returns a function reference. I have to use Node’s require function to use the express module.
const app = express();
  • express();: Creates a object to start a new Express application.
const port = process.env.PORT || 5000;
  • Set a port number instead of 3000 which is already set as default.
  • **process.env.PORT   5000;**: In .env file, I already set a PORT number.
require("dotenv").config();
  • DotEnv is a lightweight npm package that automatically loads environment variables from a . env file into the process. env object.
app.listen(port, console.log(`Server running on port ${port}`));
  • app.listen(port number);: The app.listen() function is used to bind and listen the connections on the specified host and port.

Set script in package.json

  • Open the package.json -> “start”: “node server/index.js” If I run start on the command, node server/index.js will be running.
  • Open the package.json -> “dev”: “nodemon server/index.js” If I run dev on the command, nodemon server/index.js will be running.
app.use();
  • app.use() is used to bind application-level middleware to an instance of the app object which is instantiated on the creation of the Express server (router. use() for router-level middleware)
app.use(
  "/graphql",
  graphqlHTTP({
    schema,
    graphiql: process.env.NODE_ENV === "development",
  })
);
  • I can use the express-graphql library to mount a GraphQL API server on the “/graphql” HTTP endpoint
process.env.NODE_ENV === "development";
  • === (Triple equals) is a strict equality comparison operator in JavaScript, which returns false for the values which are not of a similar type. This operator performs type casting for equality. If we compare 2 with “2” using ===, then it will return a false value.

  • If process.env.NODE_ENV is ‘development’, true will be returned.

const {projects, clients} = require('./sampleData.js')

-----In the sampleData.js------
const projects = [
  { ... },
  { ... },
  { ... },
];
const clients = [
  { ... },
  { ... },
  { ... },
];

The variables in the sampleData.js are put in projects and clients variables.

Open graphql tool to test query

  • localhost:5000/graphql

  • To test type,

{
	client(id: "2") {
    id,
    name,
    email,
    phone,
  }
}
// result
{
  "data": {
    "client": {
      "id": "2",
      "name": "Natasha Romanova",
      "email": "blackwidow@gmail.com",
      "phone": "223-567-3322"
    }
  }
}

What is resolve() ?

clients: {
      type: new GraphQLList(ClientType),
      resolve(parent, args){
        return clients;
      }
    }
  • resolve(): Resolver is a collection of functions that generate response for a GraphQL query. In simple terms, a resolver acts as a GraphQL query handler

Exclude .env file when committing

  • Using .gitignore file -> Make a .gitignore file and enter .env
  • Type command git rm --cached .env to stop tracking .env file
const connectDB = async () => {};

async() ?

  • Asynchronous code allows the program to be executed immediately where the synchronous code will block further execution of the remaining code until it finishes the current one.

Arrow function

let func = (arg1, arg2, ..., argN) => expression;

Same with

let func = function(arg1, arg2, ..., argN) {
  return expression;
};

For example,

let sum = (a, b) => {
  let result = a + b;
  return result;
};

//function expression
let age = prompt("What is your age?", 18);

let welcome = age < 18 ? () => alert("Hello!") : () => alert("Greetings!");

welcome();

Connect to MongoDB

const conn = await mongoose.connect(precess.env.MONGO_URI);
  • I can connect to MongoDB with the mongoose.connect()

colors

console.log(`MongoDB Connected: ${conn.connection.host}`.cyan.underline.bold);
  • cyan.underline.bold: The error log will be colored

JSON Schema - enum

const ProjectSchema = new mongoose.Schema({
  name: {
    type: String,
  },
  description: {
    type: String,
  },
  status: {
    type: String,
    enum: ["Not Started", "In progress", "Completed"],
  },
});
  • I can define a set of values in a JSON Schema, but then in JSON data it takes only one of those values

GraphQL Queries & Mutations

These are the GraphQL queries and mutations for the YouTube course.

Get names of all clients

{
  clients {
    name
  }
}

Get a single client name and email

{
  client(id: 1) {
    name
    email
  }
}

Get name and status of all projects

{
  projects {
    name
    status
  }
}

Get a single project name, description along with the client name and email

{
  project(id: 1) {
    name
    description,
    client {
      name
      email
    }
  }
}

Create a new client and return all data

mutation {
  addClient(name: "Tony Stark", email: "ironman@gmail.com", phone: "955-365-3376") {
    id
    name
    email
    phone
  }
}

Delete a client and return id

mutation {
  deleteClient(id: 1) {
    id
  }
}

Create a new project and return name and description

mutation {
  addProject(name: "Mobile App", description: "This is the project description", status: "new", clientId: "1") {
   name
   description
  }
}

Update a project status and return name and status

mutation {
  updateProject(status: "completed") {
   name
   status
  }
}

To create a frond-end job

  • Open another terminal and type npx create-react-app client
  • React app is going to be installed in project-management folder

For front-end, install several tools

npm i @apollo/client graphql react-router-dom react-icons
  • @apollo/client: Apollo Client is a fully-featured caching GraphQL client with integrations for React, Angular, and more. It allows you to easily build UI components that fetch data via GraphQL.

  • react-router-dom: React Router DOM enables you to implement dynamic routing in a web app.

import { ApolloProvider, ApolloClient, InMemoryCache } from "@apollo/client";
  • ApolloProvider: ApolloProvider wraps your React app and places Apollo Client on the context, which enables you to access it from anywhere in your component tree.
  • ApolloClient: Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data, all while automatically updating your UI.
  • InMemoryCache: An in-memory cache is a data storage layer that sits between applications and databases to deliver responses with high speeds by storing data from earlier requests or copied directly from databases.
import { gql, useQuery } from "@apollo/client";
  • gql:
  • useQuery:
import { useMutation } from '@apollo/client'
const onSubmit = (e) => {
    e.preventDefault();
    console.log(name, email, phone);
  }
  • e.preventDefault(): The preventDefault() method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur.

Leave a comment