Merge branch 'master' into master
This commit is contained in:
Generated
+3333
-1406
File diff suppressed because it is too large
Load Diff
+182
-40
@@ -5,35 +5,54 @@ import links from "../constants/page-links"
|
|||||||
import { isMediumUsernameValid, isGitHubUsernameValid } from "../utils/validation"
|
import { isMediumUsernameValid, isGitHubUsernameValid } from "../utils/validation"
|
||||||
import { ToolsIcon, XCircleIcon } from "@primer/octicons-react";
|
import { ToolsIcon, XCircleIcon } from "@primer/octicons-react";
|
||||||
|
|
||||||
const AddonsItem = ({inputId, inputChecked, onInputChange, Icon, onIconClick, ...props}) => {
|
const AddonsItem = ({ inputId, inputChecked, onInputChange, Options, onIconClick, ...props }) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const Icon = open ? XCircleIcon : ToolsIcon;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="py-2 flex justify-start items-center text-sm sm:text-lg">
|
<>
|
||||||
<label htmlFor={inputId} className="cursor-pointer flex items-center">
|
<div className="py-2 flex justify-start items-center text-sm sm:text-lg">
|
||||||
<input
|
<label htmlFor={inputId} className="cursor-pointer flex items-center">
|
||||||
type="checkbox"
|
<input
|
||||||
id={inputId}
|
type="checkbox"
|
||||||
checked={inputChecked}
|
id={inputId}
|
||||||
onChange={onInputChange}
|
checked={inputChecked}
|
||||||
/>
|
onChange={onInputChange}
|
||||||
<span className="pl-4">{props.children}</span>
|
/>
|
||||||
</label>
|
<span className="pl-4">{props.children}</span>
|
||||||
{
|
</label>
|
||||||
Icon?
|
{Options && (
|
||||||
<button onClick={onIconClick} className="flex ml-3 focus:bg-gray-400" style={{outline: "none"}}>
|
<button
|
||||||
|
onClick={() => setOpen(!open)}
|
||||||
|
className="flex ml-3 focus:bg-gray-400"
|
||||||
|
style={{ outline: "none" }}
|
||||||
|
>
|
||||||
<Icon className="transform scale-100 md:scale-125" />
|
<Icon className="transform scale-100 md:scale-125" />
|
||||||
</button>
|
</button>
|
||||||
:''
|
)}
|
||||||
}
|
</div>
|
||||||
|
{Options && open && Options}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomizeOptions = ({ title, CustomizationOptions }) => (
|
||||||
|
<div
|
||||||
|
className={`border-2 border-solid border-gray-900 bg-gray-100 p-2 ml-8`}
|
||||||
|
style={{ maxWidth: "21rem" }}
|
||||||
|
>
|
||||||
|
<header className="text-base sm:text-lg">{title}</header>
|
||||||
|
<hr className="border-gray-500" />
|
||||||
|
<div className="text-sm sm:text-lg flex flex-col mt-2 ml-0 md:ml-4">
|
||||||
|
{CustomizationOptions}
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
}
|
);
|
||||||
|
|
||||||
|
|
||||||
const CustomizeBadge = ({githubName, badgeOptions, onBadgeUpdate}) => {
|
const CustomizeBadge = ({githubName, badgeOptions, onBadgeUpdate}) => {
|
||||||
return (
|
return (
|
||||||
<div className={`border-2 border-solid border-gray-900 bg-gray-100 p-2 ml-8`} style={{maxWidth: '21rem'}}>
|
<>
|
||||||
<header className="text-base sm:text-lg">Customize Badge</header>
|
|
||||||
<hr className="border-gray-500"/>
|
|
||||||
<div className="text-sm sm:text-lg flex flex-col mt-2 ml-0 md:ml-4">
|
|
||||||
<label htmlFor="badge-style">Style:
|
<label htmlFor="badge-style">Style:
|
||||||
<select
|
<select
|
||||||
id="badge-style"
|
id="badge-style"
|
||||||
@@ -83,13 +102,90 @@ const CustomizeBadge = ({githubName, badgeOptions, onBadgeUpdate}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CustomizeGithubStatsBase = ({ prefix, options, onUpdate }) =>
|
||||||
|
<>
|
||||||
|
<label htmlFor={`${prefix}-theme`}>Theme:
|
||||||
|
<select
|
||||||
|
id={`${prefix}-theme`}
|
||||||
|
onChange={({target: { value }}) => onUpdate("theme", value)}
|
||||||
|
defaultValue={options.theme}
|
||||||
|
>
|
||||||
|
<option value="none">none</option>
|
||||||
|
<option value="dark">Dark</option>
|
||||||
|
<option value="radical">Radical</option>
|
||||||
|
<option value="merko">Merko</option>
|
||||||
|
<option value="gruvbox">Gruvbox</option>
|
||||||
|
<option value="tokyonight">Tokyonight</option>
|
||||||
|
<option value="onedark">Onedark</option>
|
||||||
|
<option value="cobalt">Cobalt</option>
|
||||||
|
<option value="synthwave">Synthwave</option>
|
||||||
|
<option value="highcontrast">Highcontrast</option>
|
||||||
|
<option value="dracula">Dracula</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label htmlFor={`${prefix}-title-color`}>Title Color:
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
id={`${prefix}-title-color`}
|
||||||
|
defaultValue={`#${options.titleColor}`}
|
||||||
|
className="w-6"
|
||||||
|
onChange={(e) => onUpdate('titleColor', e.target.value.replace('#', ''))}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor={`${prefix}-text-color`}>Text Color:
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
id={`${prefix}-text-color`}
|
||||||
|
defaultValue={`#${options.textColor}`}
|
||||||
|
className="w-6"
|
||||||
|
onChange={(e) => onUpdate('textColor', e.target.value.replace('#', ''))}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor={`${prefix}-bg-color`}>Background Color:
|
||||||
|
<input
|
||||||
|
type="color"
|
||||||
|
id={`${prefix}-bg-color`}
|
||||||
|
defaultValue={`#${options.bgColor}`}
|
||||||
|
className="w-6"
|
||||||
|
onChange={(e) => onUpdate('bgColor', e.target.value.replace('#', ''))}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor={`${prefix}-hide-border`}>Hide border:
|
||||||
|
<input
|
||||||
|
id={`${prefix}-hide-border`}
|
||||||
|
type="checkbox"
|
||||||
|
checked={options.hideBorder}
|
||||||
|
onChange={(e) => onUpdate('hideBorder', e.target.checked)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor={`${prefix}-cache-seconds`}>Cache Seconds:
|
||||||
|
<input
|
||||||
|
id={`${prefix}-cache-seconds`}
|
||||||
|
type="number"
|
||||||
|
min={1800}
|
||||||
|
max={86400}
|
||||||
|
placeholder={1800}
|
||||||
|
defaultValue={options.cacheSeconds}
|
||||||
|
onChange={(e) => onUpdate('cacheSeconds', e.target.value)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label htmlFor={`${prefix}-locale`}>Locale:
|
||||||
|
<input
|
||||||
|
id={`${prefix}-locale`}
|
||||||
|
type="text"
|
||||||
|
placeholder="en"
|
||||||
|
defaultValue={options.locale}
|
||||||
|
onChange={(e) => onUpdate('locale', e.target.value)}
|
||||||
|
size="2"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</>
|
||||||
|
|
||||||
const Addons = props => {
|
const Addons = props => {
|
||||||
const [customizeBadgeOpen, setCustomizeOpen] = useState(false);
|
|
||||||
const [debounce, setDebounce] = useState(undefined);
|
const [debounce, setDebounce] = useState(undefined);
|
||||||
const [badgeOptions, setBadgeOptions] = useState({
|
const [badgeOptions, setBadgeOptions] = useState({
|
||||||
badgeStyle: props.data.badgeStyle,
|
badgeStyle: props.data.badgeStyle,
|
||||||
@@ -105,6 +201,26 @@ const Addons = props => {
|
|||||||
})
|
})
|
||||||
}, [props.data.badgeStyle, props.data.badgeColor, props.data.badgeLabel])
|
}, [props.data.badgeStyle, props.data.badgeColor, props.data.badgeLabel])
|
||||||
|
|
||||||
|
const [githubStatsOptions, setGithubStatsOptions] = useState({
|
||||||
|
...props.data.githubStatsOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setGithubStatsOptions({
|
||||||
|
...props.data.githubStatsOptions
|
||||||
|
})
|
||||||
|
}, [props.data.githubStatsOptions])
|
||||||
|
|
||||||
|
const [topLanguagesOptions, setTopLanguagesOptions] = useState({
|
||||||
|
...props.data.topLanguagesOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTopLanguagesOptions({
|
||||||
|
...props.data.topLanguagesOptions
|
||||||
|
})
|
||||||
|
}, [props.data.topLanguagesOptions])
|
||||||
|
|
||||||
const blogPostPorkflow = () => {
|
const blogPostPorkflow = () => {
|
||||||
let payload = {
|
let payload = {
|
||||||
dev: {
|
dev: {
|
||||||
@@ -133,10 +249,6 @@ const Addons = props => {
|
|||||||
document.body.removeChild(tempElement)
|
document.body.removeChild(tempElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onCustomizeClick = () => {
|
|
||||||
setCustomizeOpen(!customizeBadgeOpen);
|
|
||||||
}
|
|
||||||
|
|
||||||
const onBadgeUpdate = (option, value) => {
|
const onBadgeUpdate = (option, value) => {
|
||||||
const callback = () => {
|
const callback = () => {
|
||||||
let newVal = (option==='badgeLabel' && value==='')?'Profile views':value;
|
let newVal = (option==='badgeLabel' && value==='')?'Profile views':value;
|
||||||
@@ -146,6 +258,19 @@ const Addons = props => {
|
|||||||
clearTimeout(debounce);
|
clearTimeout(debounce);
|
||||||
setDebounce(setTimeout(callback, 300));
|
setDebounce(setTimeout(callback, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onStatsUpdate = (option, value) => {
|
||||||
|
const newStatsOptions = {...githubStatsOptions, [option]: value}
|
||||||
|
setGithubStatsOptions(newStatsOptions)
|
||||||
|
props.handleDataChange("githubStatsOptions", {target: {value: newStatsOptions}})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTopLangUpdate = (option, value) => {
|
||||||
|
const newLangOptions = {...topLanguagesOptions, [option]: value}
|
||||||
|
setTopLanguagesOptions(newLangOptions)
|
||||||
|
props.handleDataChange("topLanguagesOptions", {target: {value: newLangOptions}})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-start flex-col w-full px-2 sm:px-6 mb-10">
|
<div className="flex justify-center items-start flex-col w-full px-2 sm:px-6 mb-10">
|
||||||
<div className="text-xl sm:text-2xl font-bold font-title mt-2 mb-2">
|
<div className="text-xl sm:text-2xl font-bold font-title mt-2 mb-2">
|
||||||
@@ -155,20 +280,21 @@ const Addons = props => {
|
|||||||
inputId="visitors-count"
|
inputId="visitors-count"
|
||||||
inputChecked={props.data.visitorsBadge}
|
inputChecked={props.data.visitorsBadge}
|
||||||
onInputChange={() => props.handleCheckChange("visitorsBadge")}
|
onInputChange={() => props.handleCheckChange("visitorsBadge")}
|
||||||
Icon={ customizeBadgeOpen ? XCircleIcon : ToolsIcon }
|
Options={
|
||||||
onIconClick={onCustomizeClick}
|
<CustomizeOptions
|
||||||
|
title="Customize Badge"
|
||||||
|
CustomizationOptions={
|
||||||
|
<CustomizeBadge
|
||||||
|
githubName={props.social.github}
|
||||||
|
badgeOptions={badgeOptions}
|
||||||
|
onBadgeUpdate={onBadgeUpdate}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
display visitors count badge
|
display visitors count badge
|
||||||
</AddonsItem>
|
</AddonsItem>
|
||||||
{
|
|
||||||
customizeBadgeOpen?
|
|
||||||
<CustomizeBadge
|
|
||||||
githubName={props.social.github}
|
|
||||||
badgeOptions={badgeOptions}
|
|
||||||
onBadgeUpdate={onBadgeUpdate}
|
|
||||||
/>
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
<AddonsItem
|
<AddonsItem
|
||||||
inputId="github-profile-trophy"
|
inputId="github-profile-trophy"
|
||||||
inputChecked={props.data.githubProfileTrophy}
|
inputChecked={props.data.githubProfileTrophy}
|
||||||
@@ -180,6 +306,14 @@ const Addons = props => {
|
|||||||
inputId="github-stats"
|
inputId="github-stats"
|
||||||
inputChecked={props.data.githubStats}
|
inputChecked={props.data.githubStats}
|
||||||
onInputChange={() => props.handleCheckChange("githubStats")}
|
onInputChange={() => props.handleCheckChange("githubStats")}
|
||||||
|
Options={
|
||||||
|
<CustomizeOptions
|
||||||
|
title="Customize Github Stats Card"
|
||||||
|
CustomizationOptions={
|
||||||
|
<CustomizeGithubStatsBase prefix="stats" options={githubStatsOptions} onUpdate={onStatsUpdate}/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
display github profile stats card
|
display github profile stats card
|
||||||
</AddonsItem>
|
</AddonsItem>
|
||||||
@@ -187,6 +321,14 @@ const Addons = props => {
|
|||||||
inputId="top-languages"
|
inputId="top-languages"
|
||||||
inputChecked={props.data.topLanguages}
|
inputChecked={props.data.topLanguages}
|
||||||
onInputChange={() => props.handleCheckChange("topLanguages")}
|
onInputChange={() => props.handleCheckChange("topLanguages")}
|
||||||
|
Options={
|
||||||
|
<CustomizeOptions
|
||||||
|
title="Customize Top Skills Card"
|
||||||
|
CustomizationOptions={
|
||||||
|
<CustomizeGithubStatsBase prefix="top-lang" options={topLanguagesOptions} onUpdate={onTopLangUpdate}/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
display top skills
|
display top skills
|
||||||
</AddonsItem>
|
</AddonsItem>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import links from "../constants/page-links"
|
|||||||
import gsap from "gsap"
|
import gsap from "gsap"
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { Link } from "gatsby"
|
import { Link } from "gatsby"
|
||||||
|
import { act } from "react-dom/test-utils"
|
||||||
|
|
||||||
const Header = props => {
|
const Header = props => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
@@ -14,10 +15,12 @@ const Header = props => {
|
|||||||
|
|
||||||
const { stargazers_count, forks_count } = response.data
|
const { stargazers_count, forks_count } = response.data
|
||||||
|
|
||||||
setstats({
|
act(() =>
|
||||||
starsCount: stargazers_count,
|
setstats({
|
||||||
forksCount: forks_count,
|
starsCount: stargazers_count,
|
||||||
})
|
forksCount: forks_count,
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const [stats, setstats] = useState({
|
const [stats, setstats] = useState({
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { isMediumUsernameValid } from "../utils/validation"
|
import { isMediumUsernameValid } from "../utils/validation"
|
||||||
import { icons, skills, skillWebsites } from "../constants/skills"
|
import { icons, skills, skillWebsites } from "../constants/skills"
|
||||||
|
import { githubStatsLinkGenerator, topLanguagesLinkGenerator } from "../utils/link-generators"
|
||||||
|
|
||||||
const Markdown = props => {
|
const Markdown = props => {
|
||||||
const Title = props => {
|
const Title = props => {
|
||||||
@@ -123,15 +124,11 @@ const Markdown = props => {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
const GitHubStats = props => {
|
const GitHubStats = ({ show, github, options }) => {
|
||||||
let link =
|
if (show) {
|
||||||
"https://github-readme-stats.vercel.app/api?username=" +
|
|
||||||
props.github +
|
|
||||||
"&show_icons=true"
|
|
||||||
if (props.show) {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{`<p> <img align="center" src="${link}" alt="${props.github}" /></p>`}
|
{`<p> <img align="center" src="${githubStatsLinkGenerator({github: github, options})}" alt="${github}" /></p>`}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
</>
|
</>
|
||||||
@@ -204,15 +201,11 @@ const Markdown = props => {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
const DisplayTopLanguages = props => {
|
const DisplayTopLanguages = props => {
|
||||||
let link =
|
|
||||||
"https://github-readme-stats.vercel.app/api/top-langs/?username=" +
|
|
||||||
props.github +
|
|
||||||
"&layout=compact"
|
|
||||||
if (props.show) {
|
if (props.show) {
|
||||||
if (!props.showStats) {
|
if (!props.showStats) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{`<p><img align="center" src="${link}" alt="${props.github}" /></p>`}
|
{`<p><img align="center" src="${topLanguagesLinkGenerator({github: props.github, options: props.options})}" alt="${props.github}" /></p>`}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
</>
|
</>
|
||||||
@@ -220,7 +213,7 @@ const Markdown = props => {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{`<p><img align="left" src="${link}" alt="${props.github}" /></p>`}
|
{`<p><img align="left" src="${topLanguagesLinkGenerator({github: props.github, options: props.options })}" alt="${props.github}" /></p>`}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
</>
|
</>
|
||||||
@@ -491,16 +484,17 @@ const Markdown = props => {
|
|||||||
show={props.data.topLanguages}
|
show={props.data.topLanguages}
|
||||||
showStats={props.data.githubStats}
|
showStats={props.data.githubStats}
|
||||||
github={props.social.github}
|
github={props.social.github}
|
||||||
|
options={props.data.topLanguagesOptions}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
<>
|
<>
|
||||||
<GitHubStats
|
<GitHubStats
|
||||||
show={props.data.githubStats}
|
show={props.data.githubStats}
|
||||||
github={props.social.github}
|
github={props.social.github}
|
||||||
|
options={props.data.githubStatsOptions}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Markdown
|
export default Markdown
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import { icons, skills, skillWebsites } from "../constants/skills"
|
import { icons, skills, skillWebsites } from "../constants/skills"
|
||||||
|
import { githubStatsLinkGenerator, topLanguagesLinkGenerator } from "../utils/link-generators"
|
||||||
|
|
||||||
const MarkdownPreview = props => {
|
const MarkdownPreview = props => {
|
||||||
const TitlePreview = props => {
|
const TitlePreview = props => {
|
||||||
@@ -267,29 +268,22 @@ const MarkdownPreview = props => {
|
|||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const GitHubStatsPreview = props => {
|
|
||||||
let link =
|
const GitHubStatsPreview = ({github, options, show })=> {
|
||||||
"https://github-readme-stats.vercel.app/api?username=" +
|
if (show) {
|
||||||
props.github +
|
|
||||||
"&show_icons=true"
|
|
||||||
if (props.show) {
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center mx-4 mb-4">
|
<div className="text-center mx-4 mb-4">
|
||||||
<img src={link} alt={props.github} />
|
<img src={githubStatsLinkGenerator({github, options})} alt={github} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const TopLanguagesPreview = props => {
|
const TopLanguagesPreview = ({github, options, show})=> {
|
||||||
let link =
|
if (show) {
|
||||||
"https://github-readme-stats.vercel.app/api/top-langs/?username=" +
|
|
||||||
props.github +
|
|
||||||
"&layout=compact"
|
|
||||||
if (props.show) {
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center mx-4 mb-4">
|
<div className="text-center mx-4 mb-4">
|
||||||
<img src={link} alt={props.github} />
|
<img src={topLanguagesLinkGenerator({github, options})} alt={props.github} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -348,10 +342,12 @@ const MarkdownPreview = props => {
|
|||||||
<TopLanguagesPreview
|
<TopLanguagesPreview
|
||||||
show={props.data.topLanguages}
|
show={props.data.topLanguages}
|
||||||
github={props.social.github}
|
github={props.social.github}
|
||||||
|
options={props.data.topLanguagesOptions}
|
||||||
/>
|
/>
|
||||||
<GitHubStatsPreview
|
<GitHubStatsPreview
|
||||||
show={props.data.githubStats}
|
show={props.data.githubStats}
|
||||||
github={props.social.github}
|
github={props.social.github}
|
||||||
|
options={props.data.githubStatsOptions}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+69
-14
@@ -1,7 +1,12 @@
|
|||||||
import React from "react"
|
import React, {useState} from "react"
|
||||||
import { icons, categorizedSkills } from "../constants/skills"
|
import { icons, categorizedSkills } from "../constants/skills"
|
||||||
|
import { SearchIcon, XIcon } from "@primer/octicons-react";
|
||||||
|
|
||||||
|
|
||||||
const Skills = props => {
|
const Skills = props => {
|
||||||
|
const [search, setSearch] = useState('')
|
||||||
|
const [debounce, setDebounce] = useState(undefined);
|
||||||
|
const inputRef = React.createRef()
|
||||||
const createSkill = skill => {
|
const createSkill = skill => {
|
||||||
return (
|
return (
|
||||||
<div className="w-1/3 sm:w-1/4 my-6" key={skill}>
|
<div className="w-1/3 sm:w-1/4 my-6" key={skill}>
|
||||||
@@ -22,28 +27,78 @@ const Skills = props => {
|
|||||||
/>
|
/>
|
||||||
<span className="tooltiptext">{skill}</span>
|
<span className="tooltiptext">{skill}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const onSearchChange = (value) => {
|
||||||
<div className="px-2 sm:px-6 mb-10">
|
const callback = () => {
|
||||||
<div className="text-xl sm:text-2xl font-bold font-title mt-2 mb-2">
|
setSearch(value)
|
||||||
Skills
|
}
|
||||||
</div>
|
clearTimeout(debounce)
|
||||||
|
setDebounce(setTimeout(callback, 50))
|
||||||
|
}
|
||||||
|
|
||||||
{Object.keys(categorizedSkills).map(key => (
|
return (
|
||||||
<div key={key}>
|
<div className="px-2 sm:px-6 mb-10 ">
|
||||||
<h4 className="text-sm sm:text-xl text-gray-900 text-left">
|
<div className="text-xl sm:text-2xl font-bold font-title mt-2 mb-4 flex justify-between">
|
||||||
{categorizedSkills[key].title}
|
Skills
|
||||||
</h4>
|
<div className="relative flex">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
onChange={(e) => onSearchChange(e.target.value)}
|
||||||
|
className="leading:none text-xs my-0 py-1 px-2 pr-8 sm:text-xl border-2 border-gray-900 focus:border-blue-700 placeholder-gray-700"
|
||||||
|
placeholder="Search Skills"
|
||||||
|
ref = {inputRef}
|
||||||
|
/>
|
||||||
|
<span className="absolute" style={{right:"10px"}}>
|
||||||
|
{(search !== '')
|
||||||
|
?<button className="focus:outline-none" onClick={() => {
|
||||||
|
setSearch('')
|
||||||
|
inputRef.current.value = ''
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
<XIcon size={16} className="mb-1 transform scale-100 md:scale-125"/>
|
||||||
|
</button>
|
||||||
|
:<SearchIcon size={16} className="mb-1 transform scale-100 md:scale-125"/>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{Object.keys(categorizedSkills)
|
||||||
|
.filter(key => {
|
||||||
|
let filtered = categorizedSkills[key].skills.filter(skill => {
|
||||||
|
return skill.includes(search.toLowerCase())
|
||||||
|
})
|
||||||
|
return filtered.length !== 0
|
||||||
|
})
|
||||||
|
.map(key => (
|
||||||
|
<div key={key} className="divide-y divide-gray-500">
|
||||||
|
<div className="text-sm sm:text-xl text-gray-900 text-left py-1">
|
||||||
|
{categorizedSkills[key].title}
|
||||||
|
</div>
|
||||||
<div className="flex justify-start items-center flex-wrap w-full mb-6 pl-4 sm:pl-10">
|
<div className="flex justify-start items-center flex-wrap w-full mb-6 pl-4 sm:pl-10">
|
||||||
{categorizedSkills[key].skills.map(skill => createSkill(skill))}
|
{categorizedSkills[key].skills
|
||||||
|
.filter(skill => {
|
||||||
|
return skill.includes(search.toLowerCase())
|
||||||
|
})
|
||||||
|
.map(skill => createSkill(skill))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<span className="flex justify-center text-gray-900">
|
||||||
|
{(Object.keys(categorizedSkills)
|
||||||
|
.filter(key => {
|
||||||
|
let filtered = categorizedSkills[key].skills.filter(skill => {
|
||||||
|
return skill.includes(search.toLowerCase())
|
||||||
|
})
|
||||||
|
return filtered.length !== 0
|
||||||
|
})
|
||||||
|
.length === 0)?"No Results Found":""}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Skills
|
export default Skills
|
||||||
|
|||||||
+64
-30
@@ -6,7 +6,7 @@ const categorizedSkills = {
|
|||||||
"c",
|
"c",
|
||||||
"cplusplus",
|
"cplusplus",
|
||||||
"csharp",
|
"csharp",
|
||||||
"go",
|
"go",
|
||||||
"java",
|
"java",
|
||||||
"javascript",
|
"javascript",
|
||||||
"typescript",
|
"typescript",
|
||||||
@@ -180,6 +180,7 @@ const categorizedSkills = {
|
|||||||
"invision",
|
"invision",
|
||||||
"framer",
|
"framer",
|
||||||
"postman",
|
"postman",
|
||||||
|
"solidworks",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -214,18 +215,27 @@ const categorizedSkills = {
|
|||||||
|
|
||||||
other: {
|
other: {
|
||||||
title: "Other",
|
title: "Other",
|
||||||
skills: ["linux", "git"],
|
skills: ["linux", "git", "arduino"],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const icons = {
|
const icons = {
|
||||||
vuejs: "https://devicons.github.io/devicon/devicon.git/icons/vuejs/vuejs-original-wordmark.svg",
|
vuejs:
|
||||||
react: "https://devicons.github.io/devicon/devicon.git/icons/react/react-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/vuejs/vuejs-original-wordmark.svg",
|
||||||
angularjs: "https://devicons.github.io/devicon/devicon.git/icons/angularjs/angularjs-original.svg",
|
react:
|
||||||
aws: "https://devicons.github.io/devicon/devicon.git/icons/amazonwebservices/amazonwebservices-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/react/react-original-wordmark.svg",
|
||||||
android: "https://devicons.github.io/devicon/devicon.git/icons/android/android-original-wordmark.svg",
|
angularjs:
|
||||||
backbonejs: "https://devicons.github.io/devicon/devicon.git/icons/backbonejs/backbonejs-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/angularjs/angularjs-original.svg",
|
||||||
bootstrap: "https://devicons.github.io/devicon/devicon.git/icons/bootstrap/bootstrap-plain.svg",
|
aws:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/amazonwebservices/amazonwebservices-original-wordmark.svg",
|
||||||
|
android:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/android/android-original-wordmark.svg",
|
||||||
|
arduino:
|
||||||
|
"https://cdn.worldvectorlogo.com/logos/arduino-1.svg",
|
||||||
|
backbonejs:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/backbonejs/backbonejs-original-wordmark.svg",
|
||||||
|
bootstrap:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/bootstrap/bootstrap-plain.svg",
|
||||||
c: "https://devicons.github.io/devicon/devicon.git/icons/c/c-original.svg",
|
c: "https://devicons.github.io/devicon/devicon.git/icons/c/c-original.svg",
|
||||||
canvasjs: "https://raw.githubusercontent.com/Hardik0307/Hardik0307/master/assets/canvasjs-charts.svg",
|
canvasjs: "https://raw.githubusercontent.com/Hardik0307/Hardik0307/master/assets/canvasjs-charts.svg",
|
||||||
coffeescript: "https://devicons.github.io/devicon/devicon.git/icons/coffeescript/coffeescript-original-wordmark.svg",
|
coffeescript: "https://devicons.github.io/devicon/devicon.git/icons/coffeescript/coffeescript-original-wordmark.svg",
|
||||||
@@ -247,26 +257,48 @@ const icons = {
|
|||||||
java: "https://devicons.github.io/devicon/devicon.git/icons/java/java-original-wordmark.svg",
|
java: "https://devicons.github.io/devicon/devicon.git/icons/java/java-original-wordmark.svg",
|
||||||
javascript: "https://devicons.github.io/devicon/devicon.git/icons/javascript/javascript-original.svg",
|
javascript: "https://devicons.github.io/devicon/devicon.git/icons/javascript/javascript-original.svg",
|
||||||
ionic: "https://upload.wikimedia.org/wikipedia/commons/d/d1/Ionic_Logo.svg",
|
ionic: "https://upload.wikimedia.org/wikipedia/commons/d/d1/Ionic_Logo.svg",
|
||||||
laravel: "https://devicons.github.io/devicon/devicon.git/icons/laravel/laravel-plain-wordmark.svg",
|
laravel:
|
||||||
meteor: "https://devicons.github.io/devicon/devicon.git/icons/meteor/meteor-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/laravel/laravel-plain-wordmark.svg",
|
||||||
mongodb: "https://devicons.github.io/devicon/devicon.git/icons/mongodb/mongodb-original-wordmark.svg",
|
meteor:
|
||||||
mysql: "https://devicons.github.io/devicon/devicon.git/icons/mysql/mysql-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/meteor/meteor-original-wordmark.svg",
|
||||||
nginx: "https://devicons.github.io/devicon/devicon.git/icons/nginx/nginx-original.svg",
|
mongodb:
|
||||||
nodejs: "https://devicons.github.io/devicon/devicon.git/icons/nodejs/nodejs-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/mongodb/mongodb-original-wordmark.svg",
|
||||||
openresty: "https://symbols-electrical.getvecta.com/stencil_25/66_openresty.403a21ca72.svg",
|
mysql:
|
||||||
oracle: "https://devicons.github.io/devicon/devicon.git/icons/oracle/oracle-original.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/mysql/mysql-original-wordmark.svg",
|
||||||
photoshop: "https://devicons.github.io/devicon/devicon.git/icons/photoshop/photoshop-plain.svg",
|
nginx:
|
||||||
xd: "https://cdn.worldvectorlogo.com/logos/adobe-xd.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/nginx/nginx-original.svg",
|
||||||
php: "https://devicons.github.io/devicon/devicon.git/icons/php/php-original.svg",
|
nodejs:
|
||||||
perl: "https://api.iconify.design/logos-perl.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/nodejs/nodejs-original-wordmark.svg",
|
||||||
postgresql: "https://devicons.github.io/devicon/devicon.git/icons/postgresql/postgresql-original-wordmark.svg",
|
openresty:
|
||||||
python: "https://devicons.github.io/devicon/devicon.git/icons/python/python-original.svg",
|
"https://symbols-electrical.getvecta.com/stencil_25/66_openresty.403a21ca72.svg",
|
||||||
rails: "https://devicons.github.io/devicon/devicon.git/icons/rails/rails-original-wordmark.svg",
|
oracle:
|
||||||
redis: "https://devicons.github.io/devicon/devicon.git/icons/redis/redis-original-wordmark.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/oracle/oracle-original.svg",
|
||||||
ruby: "https://devicons.github.io/devicon/devicon.git/icons/ruby/ruby-original-wordmark.svg",
|
photoshop:
|
||||||
rust: "https://devicons.github.io/devicon/devicon.git/icons/rust/rust-plain.svg",
|
"https://devicons.github.io/devicon/devicon.git/icons/photoshop/photoshop-plain.svg",
|
||||||
sass: "https://devicons.github.io/devicon/devicon.git/icons/sass/sass-original.svg",
|
xd:
|
||||||
scala: "https://devicons.github.io/devicon/devicon.git/icons/scala/scala-original-wordmark.svg",
|
"https://cdn.worldvectorlogo.com/logos/adobe-xd.svg",
|
||||||
|
php:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/php/php-original.svg",
|
||||||
|
perl:
|
||||||
|
"https://api.iconify.design/logos-perl.svg",
|
||||||
|
postgresql:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/postgresql/postgresql-original-wordmark.svg",
|
||||||
|
python:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/python/python-original.svg",
|
||||||
|
rails:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/rails/rails-original-wordmark.svg",
|
||||||
|
redis:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/redis/redis-original-wordmark.svg",
|
||||||
|
ruby:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/ruby/ruby-original-wordmark.svg",
|
||||||
|
rust:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/rust/rust-plain.svg",
|
||||||
|
sass:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/sass/sass-original.svg",
|
||||||
|
scala:
|
||||||
|
"https://devicons.github.io/devicon/devicon.git/icons/scala/scala-original-wordmark.svg",
|
||||||
|
solidworks:
|
||||||
|
"https://cdn.worldvectorlogo.com/logos/solidworks.svg",
|
||||||
symfony: "https://symfony.com/logos/symfony_black_03.svg",
|
symfony: "https://symfony.com/logos/symfony_black_03.svg",
|
||||||
spring: "https://www.vectorlogo.zone/logos/springio/springio-icon.svg",
|
spring: "https://www.vectorlogo.zone/logos/springio/springio-icon.svg",
|
||||||
swift: "https://devicons.github.io/devicon/devicon.git/icons/swift/swift-original-wordmark.svg",
|
swift: "https://devicons.github.io/devicon/devicon.git/icons/swift/swift-original-wordmark.svg",
|
||||||
@@ -363,6 +395,8 @@ const icons = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const skillWebsites = {
|
const skillWebsites = {
|
||||||
|
arduino: "https://www.arduino.cc/",
|
||||||
|
solidworks: "https://www.solidworks.com/",
|
||||||
vuejs: "https://vuejs.org/",
|
vuejs: "https://vuejs.org/",
|
||||||
react: "https://reactjs.org/",
|
react: "https://reactjs.org/",
|
||||||
angularjs: "https://angular.io",
|
angularjs: "https://angular.io",
|
||||||
|
|||||||
+19
-2
@@ -63,7 +63,25 @@ const DEFAULT_DATA = {
|
|||||||
badgeLabel: "Profile views",
|
badgeLabel: "Profile views",
|
||||||
githubProfileTrophy: false,
|
githubProfileTrophy: false,
|
||||||
githubStats: false,
|
githubStats: false,
|
||||||
|
githubStatsOptions: {
|
||||||
|
theme: "",
|
||||||
|
titleColor: "",
|
||||||
|
textColor: "",
|
||||||
|
bgColor: "",
|
||||||
|
hideBorder: false,
|
||||||
|
cacheSeconds: null,
|
||||||
|
locale: "en",
|
||||||
|
},
|
||||||
topLanguages: false,
|
topLanguages: false,
|
||||||
|
topLanguagesOptions: {
|
||||||
|
theme: "",
|
||||||
|
titleColor: "",
|
||||||
|
textColor: "",
|
||||||
|
bgColor: "",
|
||||||
|
hideBorder: false,
|
||||||
|
cacheSeconds: null,
|
||||||
|
locale: "en",
|
||||||
|
},
|
||||||
devDynamicBlogs: false,
|
devDynamicBlogs: false,
|
||||||
mediumDynamicBlogs: false,
|
mediumDynamicBlogs: false,
|
||||||
rssDynamicBlogs: false,
|
rssDynamicBlogs: false,
|
||||||
@@ -451,11 +469,10 @@ const IndexPage = () => {
|
|||||||
)
|
)
|
||||||
setSkills(restoreDataSkills || DEFAULT_SKILLS)
|
setSkills(restoreDataSkills || DEFAULT_SKILLS)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
} finally {
|
} finally {
|
||||||
setRestore("")
|
setRestore("")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="m-4 sm:p-4">
|
<div className="m-4 sm:p-4">
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
const githubStatsStylingQueryString = options => {
|
||||||
|
const params = {
|
||||||
|
show_icons: true,
|
||||||
|
...(options.theme && options.theme !== "none") && { theme: options.theme },
|
||||||
|
...options.titleColor && { "title_color": options.titleColor },
|
||||||
|
...options.textColor && { "text_color": options.textColor},
|
||||||
|
...options.bgColor && { "bg_color": options.bgColor},
|
||||||
|
...options.hideBorder && { "hide_border": options.hideBorder},
|
||||||
|
...options.cacheSeconds && { "cache_seconds": options.cacheSeconds},
|
||||||
|
...options.locale && { "locale": options.locale},
|
||||||
|
}
|
||||||
|
const query_string = Object.entries(params).map(([key, value]) => `${key}=${value}`).join("&")
|
||||||
|
return query_string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const githubStatsLinkGenerator = ({github, options}) =>
|
||||||
|
`https://github-readme-stats.vercel.app/api?username=${github}&${githubStatsStylingQueryString(options)}`
|
||||||
|
|
||||||
|
export const topLanguagesLinkGenerator = ({github, options}) =>
|
||||||
|
`https://github-readme-stats.vercel.app/api/top-langs?username=${github}&${githubStatsStylingQueryString(options)}&layout=compact`
|
||||||
Reference in New Issue
Block a user