Sunday, March 26, 2023

Jenkins - Install Plugin manually

 you might work in environment/ company where internet and some of the connections are blocked.

In a scenario, where you would have no option rather than going through manual installation. It's really a hard stuff, but no choice. It's like when you trying to add a dependency to build environment and not allowed where you will end up in adding all the hierarchy of dependencies. Really a night mare and mostly you will hate wasting time for nothing.

Here i will add a few pieces where i would try to add "git" plugin manually.

If you use normal way, it will do it few seconds or minutes time depending on the speed of the internet, but manual installation will not take hours, but days to install a certain plugin.

Plugin : GIT

 Link : https://plugins.jenkins.io/git/

 

https://plugins.jenkins.io/git/

 




In top right corner , you will see a button “How to Install “

Click and go under 3rd option.

 

Advanced installation

The Update Center only allows the installation of the most recently released version of a plugin. In cases where an older release of the plugin is desired, a Jenkins administrator can download an older .hpi archive and manually install that on the Jenkins controller.

Jenkins stores plugins it has downloaded in the plugins directory with a .jpi suffix, whether the plugins originally had a .jpi or an .hpi suffix.

If an administrator manually copies a plugin archive into the plugins directory, it should be named with a .jpi suffix to match the file names used by plugins installed from the update center.

From the web UI

Assuming a .hpi file has been downloaded, a logged-in Jenkins administrator may upload the file from within the web UI:

  1. Navigate to the Manage Jenkins > Plugins page in the web UI.
  2. Click on the Advanced tab.
  3. Choose the .hpi file from your system or enter a URL to the archive file under the Deploy Plugin section.
  4. Deploy the plugin file.




Once a plugin file has been uploaded, the Jenkins controller must be manually restarted in order for the changes to take effect.

 

 

 

Some plugins could not be loaded due to unsatisfied dependencies. Fix these issues and restart Jenkins to re-enable these plugins.

Dependency errors:

 

 



 

 

 

 

Git plugin (5.0.0)

Plugin is missing: workflow-scm-step (400.v6b_89a_1317c9a_)

Plugin is missing: credentials (1189.vf61b_a_5e2f62e)

Plugin is missing: mailer (438.v02c7f0a_12fa_4)

Plugin is missing: ssh-credentials (305.v8f4381501156)

Plugin is missing: workflow-step-api (639.v6eca_cd8c04a_a_)

Plugin is missing: scm-api (631.v9143df5b_e4a_a)

Plugin is missing: script-security (1228.vd93135a_2fb_25)

Plugin is missing: credentials-binding (523.vd859a_4b_122e6)

Plugin is missing: git-client (4.0.0)

Plugin is missing: structs (324.va_f5d6774f3a_d)

 

Now you have to install these plugins one by one.

You can find the all the plugins in below url , this will save your effort finding plugins.
Important : make sure you check the plugin version also

https://updates.jenkins.io/download/plugins/

Friday, August 19, 2022

Springboot app with hibernate 3 - sample sql

 1.sample sql - projAllocDetails.sql


SELECT [ProjectId]

      ,[EmployeeId]

      ,[AllocationStartDate]

      ,[AllocationEndDate]

      ,[AllocationType]

      ,[ProjectRole]

      ,[IsSheduledRole]

FROM [myapp].[myapp].[tblProjectAllocations]


2. ProjectAllocationsRepository 


package com.myapp.dxt.central_scheduler.repository;


import com.myapp.dxt.central_scheduler.model.ProjectAllocations;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Modifying;

import org.springframework.data.jpa.repository.Query;

import org.springframework.stereotype.Repository;


import javax.transaction.Transactional;


@Repository

public interface ProjectAllocationsRepository extends JpaRepository<ProjectAllocations,Integer> {


    @Transactional

    @Modifying

    @Query(value = "truncate table project_allocations", nativeQuery = true)

    void truncateDeleteEffortsDetail();

}


3.Allocation DTO class


package com.myapp.dxt.central_scheduler.model;


import javax.persistence.*;

import java.io.Serializable;

import java.sql.Timestamp;


/**

 * SELECT [ProjectId]

 * ,[EmployeeId]

 * ,[AllocationStartDate]

 * ,[AllocationEndDate]

 * ,[AllocationType]

 * ,[ProjectRole]

 * ,[IsSheduledRole]

 * FROM [myapp].[myapp].[tblProjectAllocations]

 */

@Entity

@Table(name = "project_allocations")

public class ProjectAllocations implements Serializable {


    @Id

    @GeneratedValue(strategy = GenerationType.AUTO)

    private int projectAllocationsId;


    @Column(name = "projectId")

    private Integer projectId;


    @Column(name = "employeeId")

    private Integer employeeId;


    @Column(name = "allocationStartDate")

    private Timestamp allocationStartDate;


    @Column(name = "allocationEndDate")

    private Timestamp allocationEndDate;


    @Column(name = "allocationType")

    private String allocationType;


    @Column(name = "projectRole")

    private String projectRole;


    @Column(name = "isSheduledRole")

    private int isSheduledRole;


    public int getProjectAllocationsId() {

        return projectAllocationsId;

    }


    public void setProjectAllocationsId(int projectAllocationsId) {

        this.projectAllocationsId = projectAllocationsId;

    }


    public Integer getProjectId() {

        return projectId;

    }


    public void setProjectId(Integer projectId) {

        this.projectId = projectId;

    }


    public Integer getEmployeeId() {

        return employeeId;

    }


    public void setEmployeeId(Integer employeeId) {

        this.employeeId = employeeId;

    }


    public Timestamp getAllocationStartDate() {

        return allocationStartDate;

    }


    public void setAllocationStartDate(Timestamp allocationStartDate) {

        this.allocationStartDate = allocationStartDate;

    }


    public Timestamp getAllocationEndDate() {

        return allocationEndDate;

    }


    public void setAllocationEndDate(Timestamp allocationEndDate) {

        this.allocationEndDate = allocationEndDate;

    }


    public String getAllocationType() {

        return allocationType;

    }


    public void setAllocationType(String allocationType) {

        this.allocationType = allocationType;

    }


    public String getProjectRole() {

        return projectRole;

    }


    public void setProjectRole(String projectRole) {

        this.projectRole = projectRole;

    }


    public int getIsSheduledRole() {

        return isSheduledRole;

    }


    public void setIsSheduledRole(int isSheduledRole) {

        this.isSheduledRole = isSheduledRole;

    }

}


4. Service class


package com.myapp.dxt.central_scheduler.service;

import com.myapp.dxt.central_scheduler.db.MyAppExtractor;
import com.myapp.dxt.central_scheduler.model.ProjectDetails;
import com.myapp.dxt.central_scheduler.repository.ProjectDetailsRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

import static com.myapp.dxt.central_scheduler.util.Constant.MY_APP_PROJECT_DETAILS;

@Service
public class ProjectDetailsService {
private static final Logger logger = LoggerFactory.getLogger(ProjectDetailsService.class);

ProjectDetailsService() {
}

@Autowired
ProjectDetailsRepository projectDetailsRepository;

private static List<Map<String, Object>> projectDetailsList = null;

public static List<Map<String, Object>> getProjectDetailsList() {
return projectDetailsList;
}

public static void setProjectDetailsList(List<Map<String, Object>> projectDetailsList) {
ProjectDetailsService.projectDetailsList = projectDetailsList;
}

public void run() {
// extract details from myapp db
extract();
//Save data to db
save();
}

public void extract() {
logger.info("Extracting project details data");
MyAppExtractor myApp= new MyAppExtractor();
List<Map<String, Object>> extractedList = myApp.process(MY_APP_PROJECT_DETAILS);
setProjectDetailsList(extractedList);
}

public void save() {
if (!getProjectDetailsList().isEmpty()) {
logger.info("Delete existing project details table records");
projectDetailsRepository.truncateDeleteEffortsDetail();
Timestamp now = new Timestamp(System.currentTimeMillis());
for (Map<String, Object> record : getProjectDetailsList()) {
Integer projectId = (Integer) record.get("ProjectId");
String projectName = (String) record.get("ProjectName");
String account = (String) record.get("Account");
String segment = (String) record.get("Segment");
String sbu = (String) record.get("SBU");
String groupSbu = (String) record.get("GroupSBU");
String business = (String) record.get("Business");
String atc = (String) record.get("ATC");
String projectLocation = (String) record.get("ProjectLocation");
String processTemplate = (String) record.get("ProcessTemplate");
Timestamp chorusMigrationDate = (Timestamp) record.get("ChorusMigrationDate");
Timestamp chorusClosedDate = (Timestamp) record.get("ChorusClosedDate");
String practice = (String) record.get("Practice");
String chorusStatus = (String) record.get("ChorusStatus");
String managedBy = (String) record.get("ManagedBy");
Integer totalTeamSize = (Integer) record.get("TotalTeamSize");
String contractType = (String) record.get("ContractType");
String largeProgram = (String) record.get("LargeProgram");
String projectManager = (String) record.get("ProjectManager");
String velocityProjectCode = (String) record.get("VelocityProjectcode");
String velocityStatus = (String) record.get("VelocityStatus");
String projectDuration = (String) record.get("ProjectDuration");
String primaryProjectManager = (String) record.get("PrimaryProjectManager");
String mitigationTiming = (String) record.get("MitigationTiming");
String mitigationStage = (String) record.get("MitigationStage");
String asmWorkType = (String) record.get("ASMWorkType");
String underDxtPurview = (String) record.get("UnderDxTpurview");
String reasonForNotSupporting = (String) record.get("ReasonforNotSupporting");
String reason = (String) record.get("Reason");
String projectComingUnderDecPurvieWas = (String) record.get("ProjectComingUnderDECPurviewas");
String projectAccessForFacilitationAndAudits = (String) record.get("ProjectAccessforFacilitationandAudits");
String dec = (String) record.get("DEC");
String projectStartChampion = (String) record.get("ProjectStartChampion");
String acceleratorsChampion = (String) record.get("AcceleratorsChampion");
String sbuDecHead = (String) record.get("SBUDECHead");
String canDecAttendClientMeetings = (String) record.get("CanDECAttendClientMeetings");
String isTheProjectCanShowTheArtefactsUsingRemoteSharing = (String) record.get("IstheProjectCanShowtheArtefactsUsingRemoteSharing");
String accessPermissionsComments = (String) record.get("AccessPermissionsComments");
String remoteSharingComments = (String) record.get("RemoteSharingComments");
String startRightApplicability = (String) record.get("StartRightApplicability");
String reasonForSrNotApplicable = (String) record.get("ReasonforSRNotApplicable");
String startRightChampion = (String) record.get("StartRightChampion");
Timestamp velocityStartDate = (Timestamp) record.get("VelocityStartDate");
Timestamp velocityEndDate = (Timestamp) record.get("VelocityEndDate");

ProjectDetails projectDetailsEntity = new ProjectDetails();
projectDetailsEntity.setProjectId(projectId);
projectDetailsEntity.setProjectName(projectName);
projectDetailsEntity.setAccount(account);
projectDetailsEntity.setSegment(segment);
projectDetailsEntity.setSbu(sbu);
projectDetailsEntity.setGroupSbu(groupSbu);
projectDetailsEntity.setBusiness(business);
projectDetailsEntity.setAtc(atc);
projectDetailsEntity.setProjectLocation(projectLocation);
projectDetailsEntity.setProcessTemplate(processTemplate);
projectDetailsEntity.setChorusMigrationDate(chorusMigrationDate);
projectDetailsEntity.setChorusClosedDate(chorusClosedDate);
projectDetailsEntity.setPractice(practice);
projectDetailsEntity.setChorusStatus(chorusStatus);
projectDetailsEntity.setManagedBy(managedBy);
projectDetailsEntity.setTotalTeamSize(totalTeamSize);
projectDetailsEntity.setContractType(contractType);
projectDetailsEntity.setLargeProgram(largeProgram);
projectDetailsEntity.setProjectManager(projectManager);
projectDetailsEntity.setVelocityProjectCode(velocityProjectCode);
projectDetailsEntity.setVelocityStatus(velocityStatus);
projectDetailsEntity.setProjectDuration(projectDuration);
projectDetailsEntity.setPrimaryProjectManager(primaryProjectManager);
projectDetailsEntity.setMitigationTiming(mitigationTiming);
projectDetailsEntity.setMitigationStage(mitigationStage);
projectDetailsEntity.setAsmWorkType(asmWorkType);
projectDetailsEntity.setUnderDxtPurview(underDxtPurview);
projectDetailsEntity.setReasonForNotSupporting(reasonForNotSupporting);
projectDetailsEntity.setReason(reason);
projectDetailsEntity.setProjectComingUnderDecPurvieWas(projectComingUnderDecPurvieWas);
projectDetailsEntity.setProjectAccessForFacilitationAndAudits(projectAccessForFacilitationAndAudits);
projectDetailsEntity.setDeCoach(dec);
projectDetailsEntity.setProjectStartChampion(projectStartChampion);
projectDetailsEntity.setAcceleratorsChampion(acceleratorsChampion);
projectDetailsEntity.setSbuDecHead(sbuDecHead);
projectDetailsEntity.setCanDecAttendClientMeetings(canDecAttendClientMeetings);
projectDetailsEntity.setIsTheProjectCanShowTheArtefactsUsingRemoteSharing(isTheProjectCanShowTheArtefactsUsingRemoteSharing);
projectDetailsEntity.setAccessPermissionsComments(accessPermissionsComments);
projectDetailsEntity.setRemoteSharingComments(remoteSharingComments);
projectDetailsEntity.setStartRightApplicability(startRightApplicability);
projectDetailsEntity.setReasonForSrNotApplicable(reasonForSrNotApplicable);
projectDetailsEntity.setStartRightChampion(startRightChampion);
projectDetailsEntity.setVelocityStartDate(velocityStartDate);
projectDetailsEntity.setVelocityEndDate(velocityEndDate);

logger.info("Upserting project details " + projectDetailsEntity.getProjectId() + "...");
try {
projectDetailsRepository.save(projectDetailsEntity);
logger.info("Status: CREATED");
} catch (RuntimeException e) {
throw new RuntimeException("Failed to upsert project details data with project id=" + projectDetailsEntity.getProjectId() + "...");
}
}
}
}
}

Springboot app with hibernate 2 -pom.xml

 pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.myapp.dxt</groupId>
<artifactId>central_scheduler</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>central_scheduler</name>
<description>central scheduler</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.0.0.jre8</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.olap4j</groupId>
<artifactId>olap4j</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>org.olap4j</groupId>
<artifactId>olap4j-xmla</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

Springboot app with hibernate 1

 1. application.properties

server.port=8203
spring.datasource.url=jdbc:mysql://localhost:3306/central_scheduler
spring.datasource.username=root
spring.datasource.password=root@123

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=false
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

logging.level.root=warn
logging.level.com.myapp.dxt.central_scheduler=debug

Friday, January 21, 2022

Springboot Sample App - GET list of values from database

 1. get full list - all

http://localhost:8011/myapp/lov/all

This will have

  1. Controller
  2. Service and Impl
  3. Repository
  4. Model class

Controller

package com.sample.controller;


import com.sample.model.Lov;

import com.sample.service.LovServiceImpl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.HttpStatus;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;


import java.util.List;


@RestController

@RequestMapping("/myapp/lov")

public class LovController {


    @Autowired

    LovServiceImpl lovService;


    @GetMapping("/all")

    public ResponseEntity<List<Lov>> retrieveAllValues() {

        return new ResponseEntity<List<Lov>>(lovService.retrieveAllValues(), HttpStatus.OK);

    }


    @GetMapping("/fieldName")

    public ResponseEntity<List<Lov>> findByFieldName(@RequestParam String fieldName) {

        return new ResponseEntity<List<Lov>>(lovService.findByFieldName(fieldName), HttpStatus.OK);

    }


    @GetMapping("/fieldName1")

    public ResponseEntity<List<Lov>> findLovByFieldName(@RequestParam String fieldName) {

        return new ResponseEntity<List<Lov>>(lovService.findLovByFieldName(fieldName), HttpStatus.OK);

    }


    @GetMapping("/fieldId")

    public ResponseEntity<List<Lov>> findByFieldId(@RequestParam String fieldId) {

        return new ResponseEntity<List<Lov>>(lovService.findByFieldId(fieldId), HttpStatus.OK);

    }

}


-----------------

Model class

package com.sample.model;

import lombok.Data;

import javax.persistence.*;

@Entity
@Table(name = "lov")
@Data
public class Lov {

    @Id
    private int lovId;

    @Column(name = "fieldName")
    private String fieldName;

    @Column(name = "fieldId")
    private String fieldId;

    @Column(name = "value")
    private String value;
}


--------------------------------------------------------------------------------------

Service interface

package com.sample.service;

import com.sample.model.Lov;
import com.sample.repository.LovRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;


public interface LovService {

    List<Lov> retrieveAllValues();

    List<Lov> findByFieldName(String fieldName);

    List<Lov> findLovByFieldName(String fieldName);

    List<Lov> findByFieldId(String fieldId);
}


--------------------------------

Service Impl


package com.sample.service;

import com.sample.model.Lov;
import com.sample.repository.LovRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LovServiceImpl implements LovService {
    private static final Logger logger = LoggerFactory.getLogger(LovServiceImpl.class);

    @Autowired
    LovRepository lovRepository;

    public List<Lov> retrieveAllValues() {
        return lovRepository.findAll();
    }

    public List<Lov> findByFieldName(String fieldName) {
        return lovRepository.findByFieldName(fieldName);
    }

    public List<Lov> findLovByFieldName(String fieldName) {
        return lovRepository.findLovByFieldName(fieldName);
    }

    public List<Lov> findByFieldId(String fieldId) {
        return lovRepository.findByFieldId(fieldId);
    }
}

-----------------------------------------

Repository

package com.sample.repository;

import com.sample.model.Lov;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface LovRepository extends JpaRepository<Lov,Integer> {

    List<Lov> findLovByFieldName(String fieldName);

    List<Lov> findByFieldName(String fieldName);

    List<Lov> findByFieldId(String fieldId);
}


Properties


server.port=8011
#your database name is mydb
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=username
spring.datasource.password=password

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=false
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

logging.level.root=warn
logging.level.com.sample=debug 

Dependency



<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>


Monday, November 29, 2021

Ninja - React Basic 11 - Reuse Components

Let's reuse this componet we use. We already use to show the values in the 'blogs'

Now we need to show the values filter by author='mario'

let's see how are going to use this.


1. let's create a new div tag below.

<BlogList blogs={blogs} title="Mario's Blogs"/>

2. we can use filter

<BlogList blogs={blogs.filter()} title="Mario's Blogs"/>

3. Then, this filter method will call a call back function for each otem in  the array

<BlogList blogs={blogs.filter(  ()= {} )} title="Mario's Blogs"/>


a.) if true keeps in the array

b.) if false, filters outof the array

c.) and return new array with only filtered true values



4. Then passing that 'data' as a  prop.


if we show the original data


const [blogs, setBlogs] = useState([

        { title: 'My new website', body: 'lorem ipsum...', author: 'mario', id: 1 },

        { title: 'Welcome party!', body: 'lorem ipsum...', author: 'yoshi', id: 2 },

        { title: 'Web dev top tips', body: 'lorem ipsum...', author: 'mario', id: 3 }

    ]);

5. take 'blog' as arguemnt for filter

<BlogList blogs={blogs.filter(  (blogs)= {} )} title="Mario's Blogs"/>

6. check author=mario

<BlogList blogs={blogs.filter( (blog) => blog.author==='mario' )} title="Mario's Blogs"/>

Ninja - React Basic 10 - Props

Let's look at scenario where we have blogs in each page as we did it in Home page. Then we need to repeat the code block in every page.  

How to do it in a more better way.

we can make that bit of template as resusable component. eg: blog list component


{blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}


So if need to use that part in a category, tag or in any place we can just drop our component 'blog-list'.  We don't  need to repeat this total boiler plate code.


We use 'props'

with this template or component will be same, but data will be different. This helps to reuse.


1. create blog list component to hold the logic

2. create file 'BlogList.js' and create component BlogList


const BlogList = () => {

    return ();

}


export default BlogList;


3. Inside return copy paste the template we a re going to reuse. 

4. Before that let's  create a div , className=blog-list


const BlogList = () => {

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


5. Now inside home.js , we can simply use <BlogList />


return (

        <div className="home">

            <BlogList />

        </div>

    );


6. Now you get an error

'blogs' is not defined  no-undef


7. Because blogs data is not defined inside BlogList, we cannot use data defined inside another component.

8. How to solve ? There are few solutions.

8.1 Define data inside BlogList instead of Home

8.2 Use Props -> we pass this data from Home component into the BlogList component. 

9. We use second option props for three reasons


a. make BlogList component more resusable

b. We can still use data in the Home component, if needed inside Home component

c. Most important -> How to use props


10. Props is a way to pass data from a parent component to child component

11. Here Home is the parent and BlogList is the Child component

12. we are passing 'blogs' data into BlogList component

13. To do that, we create a property inside the <BlogList /> tag. You can call any name. Let's call 'blogs' as it's what we are passing.

<BlogList blogs= />

14. So this going to be a dynamic value, So curly braces.

<BlogList blogs={} />

15. value is 'blogs'. defined in top of the Home component.  

<div className="home">

            <BlogList blogs={blogs} />

 </div>

16. Now this is a prop. Now you will see an error

src\component\BlogList.js

  Line 4:14:  'blogs' is not defined  no-undef

  

17. This is cause of the next step, we are now going to use in BlogList. give tis as a parameter to BlogList


const BlogList = (blogs) => {

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


18. Now your error will disapear

19. Now we have another error


TypeError: blogs.map is not a function


20. getting an error


Failed to compile

./src/component/BlogList.js

SyntaxError: C:\Project\Project\Training\React\NetNinja\dojo-blog\src\component\BlogList.js: Identifier 'blogs' has already been declared. (1:18)


This is cause, i used 'blogs' instead of 'props' in BlogList(props)


const BlogList = (blogs) => {

    const blogs = this.props.blogs;

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


--------------------------------------

corrected code is

----------------------


const BlogList = (props) => {

    const blogs = this.props.blogs;

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


export default BlogList;



--------------------


21. But still get an error

TypeError: Cannot read properties of undefined (reading 'props')

BlogList

C:/Project/....../src/component/BlogList.js:2

  1 | const BlogList = (props) => {

> 2 |     const blogs = this.props.blogs;

  3 |     return (

  4 |         <div className='blog-list'>

  5 |             {blogs.map(((blog) => (

  

22. Reason for using 'this' keyword when accessing props 

const blogs = this.props.blogs;

23. remove 'this' and you will see page in the browser

24. Let's console out props and blogs

console.log(props,blogs);


25. you can see all the properties and blogs list.


Now we can pass multiple props

---------------------------

26. eg:title , it can be dynamic value, but here we just pass a string in Home.js

27. <BlogList blogs={blogs} title="All Blogs"/>  in Home.js

28. Now we can access this from BlogList and let's use in h2 tag and out put.


-----------------------------------------------------

const BlogList = (props) => {

    const blogs = props.blogs;

    const title = props.title;

    return (

        <div className='blog-list'>

            <h2>{title}</h2>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}

--------------------------------------------------


Further we can destructure 'props'

then we don't need const variables and can use straight away.

Code will looks like

---------------------------------------------------

const BlogList = ({blogs, title}) => {

    // const blogs = props.blogs;

    // const title = props.title;

    return (

        <div className='blog-list'>

            <h2>{title}</h2>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}

----------------------------------------------------


you can play with code and check what happens after changing name of the props and variables.

Yu can see , it will  still work without any issues.

const BlogList = (props1=> {
    const blogs = props1.blogs;
    const title = props1.title;
    return (
        <div className='blog-list'>
            <h2>{title}</h2>
            {blogs.map(((blog=> (
                <div className='blog-preview' key={blog.id}>
                    <h2>{blog.title}</h2>
                    <p>Written by {blog.author}</p>
                </div>
            )))}
        </div>
    );
}