Merge branch 'main' of https://github.com/csarnataro/gitprofile into add-option-to-display-footer

This commit is contained in:
Christian Sarnataro 2023-01-04 20:52:23 +01:00
commit 2364f267cf
9 changed files with 1153 additions and 1185 deletions

View File

@ -267,6 +267,23 @@ const config = {
to: '2014',
},
],
// To hide the `My Projects` section, keep it empty.
externalProjects: [
{
title: 'Project Name',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc ut.',
imageUrl: 'https://via.placeholder.com/250x250',
link: 'https://example.com',
},
{
title: 'Project Name',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc ut.',
imageUrl: 'https://via.placeholder.com/250x250',
link: 'https://example.com',
},
],
// Display blog posts from your medium or dev account. (Optional)
blog: {
source: 'dev', // medium | dev
@ -542,7 +559,9 @@ Empty array will hide the certifications section.
### Projects
Your public repo from GitHub will be displayed here automatically. You can limit how many projects do you want to be displayed. Also, you can hide forked or specific repo.
#### Github Projects
Your public repo from GitHub will be displayed in the `Github Projects` section automatically. You can limit how many projects do you want to be displayed. Also, you can hide forked or specific repo.
```js
// gitprofile.config.js
@ -560,6 +579,25 @@ const config = {
};
```
#### External Projects
In this section you can showcase your external/personal projects.
```js
// gitprofile.config.js
const config = {
// ...
externalProjects: [
{
title: 'Project Name',
description: 'Description',
link: 'https://example.com',
imageUrl: 'https://via.placeholder.com/250x250',
},
],
};
```
### Blog Posts
If you have [medium](https://medium.com) or [dev](https://dev.to) account, you can show your recent blog posts in here just by providing your medium/dev username. You can limit how many posts to display (Max is `10`).

View File

@ -87,11 +87,28 @@ const config = {
/*
footer: '[...]',
*/
// To hide the `My Projects` section, keep it empty.
externalProjects: [
{
title: 'Project Name',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc ut.',
imageUrl: 'https://via.placeholder.com/250x250',
link: 'https://example.com',
},
{
title: 'Project Name',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, nunc ut.',
imageUrl: 'https://via.placeholder.com/250x250',
link: 'https://example.com',
},
],
// Display blog posts from your medium or dev account. (Optional)
blog: {
source: 'dev', // medium | dev
username: 'arifszn', // to hide blog section, keep it empty
limit: 3, // How many posts to display. Max is 10.
limit: 2, // How many posts to display. Max is 10.
},
googleAnalytics: {
id: '', // GA3 tracking id/GA4 tag id UA-XXXXXXXXX-X | G-XXXXXXXXXX

2040
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{
"name": "@arifszn/gitprofile",
"description": "Create an automatic portfolio based on GitHub profile",
"version": "2.1.1",
"version": "2.2.2",
"license": "MIT",
"author": "arifszn",
"repository": {
@ -43,7 +43,7 @@
},
"devDependencies": {
"@arifszn/blog-js": "^2.0.0",
"@vitejs/plugin-react": "^2.0.0",
"@vitejs/plugin-react": "^3.0.0",
"autoprefixer": "^10.4.4",
"axios": "^1.1.3",
"daisyui": "^2.11.0",
@ -59,7 +59,7 @@
"react-hotjar": "^5.0.0",
"react-icons": "^4.3.1",
"tailwindcss": "^3.0.23",
"vite": "^3.0.1"
"vite": "^4.0.3"
},
"keywords": [
"git-profile",

View File

@ -25,6 +25,7 @@ import { HelmetProvider } from 'react-helmet-async';
import PropTypes from 'prop-types';
import '../assets/index.css';
import { formatDistance } from 'date-fns';
import ExternalProject from './external-project';
const bgColor = 'bg-base-300';
@ -202,6 +203,11 @@ const GitProfile = ({ config }) => {
github={sanitizedConfig.github}
googleAnalytics={sanitizedConfig.googleAnalytics}
/>
<ExternalProject
loading={loading}
externalProjects={sanitizedConfig.externalProjects}
googleAnalytics={sanitizedConfig.googleAnalytics}
/>
<Blog
loading={loading}
googleAnalytics={sanitizedConfig.googleAnalytics}
@ -252,6 +258,14 @@ GitProfile.propTypes = {
email: PropTypes.string,
}),
skills: PropTypes.array,
externalProjects: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
imageUrl: PropTypes.string,
})
),
experiences: PropTypes.arrayOf(
PropTypes.shape({
company: PropTypes.string,

View File

@ -0,0 +1,171 @@
import { Fragment } from 'react';
import PropTypes from 'prop-types';
import { ga, skeleton } from '../../helpers/utils';
import LazyImage from '../lazy-image';
const displaySection = (externalProjects) => {
if (
externalProjects &&
Array.isArray(externalProjects) &&
externalProjects.length
) {
return true;
} else {
return false;
}
};
const ExternalProject = ({ externalProjects, loading, googleAnalytics }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < externalProjects.length; index++) {
array.push(
<div className="card shadow-lg compact bg-base-100" key={index}>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col">
<div className="w-full">
<div className="flex items-start px-4">
<div className="w-full">
<h2>
{skeleton({
width: 'w-32',
height: 'h-8',
className: 'mb-2 mx-auto',
})}
</h2>
<div className="avatar w-full h-full">
<div className="w-20 h-20 mask mask-squircle mx-auto">
{skeleton({
width: 'w-full',
height: 'h-full',
shape: '',
})}
</div>
</div>
<div className="mt-2">
{skeleton({
width: 'w-full',
height: 'h-4',
className: 'mx-auto',
})}
</div>
<div className="mt-2 flex items-center flex-wrap justify-center">
{skeleton({
width: 'w-full',
height: 'h-4',
className: 'mx-auto',
})}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
return array;
};
const renderExternalProjects = () => {
return externalProjects.map((item, index) => (
<a
className="card shadow-lg compact bg-base-100 cursor-pointer"
key={index}
href={item.link}
onClick={(e) => {
e.preventDefault();
try {
if (googleAnalytics?.id) {
ga.event({
action: 'Click External Project',
params: {
post: item.title,
},
});
}
} catch (error) {
console.error(error);
}
window?.open(item.link, '_blank');
}}
>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col">
<div className="w-full">
<div className="px-4">
<div className="text-center w-full">
<h2 className="font-semibold text-lg tracking-wide text-center opacity-60 mb-2">
{item.title}
</h2>
{item.imageUrl && (
<div className="avatar opacity-90">
<div className="w-20 h-20 mask mask-squircle">
<LazyImage
src={item.imageUrl}
alt={'thumbnail'}
placeholder={skeleton({
width: 'w-full',
height: 'h-full',
shape: '',
})}
/>
</div>
</div>
)}
<p className="mt-1 text-base-content text-opacity-60 text-sm">
{item.description}
</p>
</div>
</div>
</div>
</div>
</div>
</a>
));
};
return (
<Fragment>
{displaySection(externalProjects) && (
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div className="card compact bg-gradient-to-br to-base-200 from-base-100 shadow">
<div className="card-body">
<div className="mx-3 flex items-center justify-between mb-2">
<h5 className="card-title">
{loading ? (
skeleton({ width: 'w-40', height: 'h-8' })
) : (
<span className="text-base-content opacity-70">
My Projects
</span>
)}
</h5>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{loading ? renderSkeleton() : renderExternalProjects()}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</Fragment>
);
};
ExternalProject.propTypes = {
externalProjects: PropTypes.array,
loading: PropTypes.bool.isRequired,
googleAnalytics: PropTypes.object,
};
export default ExternalProject;

View File

@ -2,6 +2,7 @@ import { Fragment } from 'react';
import { AiOutlineStar, AiOutlineFork } from 'react-icons/ai';
import PropTypes from 'prop-types';
import { ga, languageColor, skeleton } from '../../helpers/utils';
import { MdInsertLink } from 'react-icons/md';
const Project = ({ repo, loading, github, googleAnalytics }) => {
if (!loading && Array.isArray(repo) && repo.length === 0) {
@ -18,7 +19,11 @@ const Project = ({ repo, loading, github, googleAnalytics }) => {
<div className="flex items-center">
<span>
<h5 className="card-title text-lg">
{skeleton({ width: 'w-32', height: 'h-8' })}
{skeleton({
width: 'w-32',
height: 'h-8',
className: 'mb-1',
})}
</h5>
</span>
</div>
@ -81,25 +86,11 @@ const Project = ({ repo, loading, github, googleAnalytics }) => {
>
<div className="flex justify-between flex-col p-8 h-full w-full">
<div>
<div className="flex items-center opacity-60">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
className="text-base-content inline-block w-5 h-5 mr-2 stroke-current"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
></path>
</svg>
<span>
<h5 className="card-title text-lg text-base-content">
{item.name}
</h5>
</span>
<div className="flex items-center">
<div className="card-title text-lg tracking-wide flex text-base-content opacity-60">
<MdInsertLink className="my-auto" />
<span className="capitalize">{item.name}</span>
</div>
</div>
<p className="mb-5 mt-1 text-base-content text-opacity-60 text-sm">
{item.description}
@ -141,10 +132,10 @@ const Project = ({ repo, loading, github, googleAnalytics }) => {
<div className="mx-3 flex items-center justify-between mb-2">
<h5 className="card-title">
{loading ? (
skeleton({ width: 'w-28', height: 'h-8' })
skeleton({ width: 'w-40', height: 'h-8' })
) : (
<span className="text-base-content opacity-70">
My Projects
GitHub Projects
</span>
)}
</h5>

View File

@ -163,6 +163,7 @@ export const sanitizeConfig = (config) => {
fileUrl: config?.resume?.fileUrl || '',
},
skills: config?.skills || [],
externalProjects: config?.externalProjects || [],
experiences: config?.experiences || [],
certifications: config?.certifications || [],
education: config?.education || [],

12
types/index.d.ts vendored
View File

@ -221,6 +221,13 @@ export interface Certifications {
link?: string;
}
export interface ExternalProjects {
title: string;
description: string;
imageUrl?: string;
link: string;
}
export interface Education {
institution?: string;
degree?: string;
@ -258,6 +265,11 @@ export interface Config {
*/
experiences?: Array<Experience>;
/**
* External Projects
*/
externalProjects?: Array<ExternalProjects>;
/**
* Certifications list
*/