Merge pull request #209 from YashKandalkar/profile-badge-customization
[add]: Profile badge customization
This commit is contained in:
+112
-3
@@ -1,10 +1,11 @@
|
||||
import React from "react"
|
||||
import React, { useState, useEffect } from "react"
|
||||
import { withPrefix } from "gatsby"
|
||||
import { latestBlogs } from "../utils/workflows"
|
||||
import links from "../constants/page-links"
|
||||
import { isMediumUsernameValid } from "../utils/validation"
|
||||
import { isMediumUsernameValid, isGitHubUsernameValid } from "../utils/validation"
|
||||
import { ToolsIcon, XCircleIcon } from "@primer/octicons-react";
|
||||
|
||||
const AddonsItem = ({ inputId, inputChecked, onInputChange, ...props }) => {
|
||||
const AddonsItem = ({inputId, inputChecked, onInputChange, Icon, onIconClick, ...props}) => {
|
||||
return (
|
||||
<div className="py-2 flex justify-start items-center text-sm sm:text-lg">
|
||||
<label htmlFor={inputId} className="cursor-pointer flex items-center">
|
||||
@@ -16,11 +17,94 @@ const AddonsItem = ({ inputId, inputChecked, onInputChange, ...props }) => {
|
||||
/>
|
||||
<span className="pl-4">{props.children}</span>
|
||||
</label>
|
||||
{
|
||||
Icon?
|
||||
<button onClick={onIconClick} className="flex ml-3 focus:bg-gray-400" style={{outline: "none"}}>
|
||||
<Icon className="transform scale-100 md:scale-125" />
|
||||
</button>
|
||||
:''
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const CustomizeBadge = ({githubName, badgeOptions, onBadgeUpdate}) => {
|
||||
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:
|
||||
<select
|
||||
id="badge-style"
|
||||
onChange={(e) => onBadgeUpdate('badgeStyle', e.target.value)}
|
||||
value = {badgeOptions.badgeStyle}
|
||||
>
|
||||
<option value="flat">Flat</option>
|
||||
<option value="flat-square">Flat Square</option>
|
||||
<option value="plastic">Plastic</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label htmlFor="badge-color">Color:
|
||||
<input
|
||||
type="color"
|
||||
id="badge-color"
|
||||
defaultValue={`#${badgeOptions.badgeColor}`}
|
||||
className="w-6"
|
||||
onChange={(e) => onBadgeUpdate('badgeColor', e.target.value.replace('#', ''))}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label htmlFor="badge-label-text">Label Text:
|
||||
<input
|
||||
type="text"
|
||||
id="badge-label-text"
|
||||
placeholder="Profile views"
|
||||
className="w-2/4 bg-gray-300 pl-2"
|
||||
onChange={(e) => onBadgeUpdate('badgeLabel', e.target.value.trim())}
|
||||
defaultValue={badgeOptions.badgeLabel}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<span className="mt-2 flex items-center">
|
||||
Preview:
|
||||
{
|
||||
isGitHubUsernameValid(githubName)?
|
||||
<img
|
||||
src={`https://komarev.com/ghpvc/`
|
||||
+ `?username=${githubName}`
|
||||
+ `&label=${encodeURI(badgeOptions.badgeLabel)}`
|
||||
+ `&color=${badgeOptions.badgeColor}`
|
||||
+ `&style=${badgeOptions.badgeStyle}`
|
||||
}
|
||||
/>
|
||||
: <span className="text-xxs md:text-sm text-red-600">Invalid GitHub username</span>
|
||||
}
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Addons = props => {
|
||||
const [customizeBadgeOpen, setCustomizeOpen] = useState(false);
|
||||
const [debounce, setDebounce] = useState(undefined);
|
||||
const [badgeOptions, setBadgeOptions] = useState({
|
||||
badgeStyle: props.data.badgeStyle,
|
||||
badgeColor: props.data.badgeColor,
|
||||
badgeLabel: props.data.badgeLabel
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setBadgeOptions({
|
||||
badgeStyle: props.data.badgeStyle,
|
||||
badgeColor: props.data.badgeColor,
|
||||
badgeLabel: props.data.badgeLabel
|
||||
})
|
||||
}, [props.data.badgeStyle, props.data.badgeColor, props.data.badgeLabel])
|
||||
|
||||
const blogPostPorkflow = () => {
|
||||
let payload = {
|
||||
dev: {
|
||||
@@ -48,6 +132,20 @@ const Addons = props => {
|
||||
tempElement.click()
|
||||
document.body.removeChild(tempElement)
|
||||
}
|
||||
|
||||
const onCustomizeClick = () => {
|
||||
setCustomizeOpen(!customizeBadgeOpen);
|
||||
}
|
||||
|
||||
const onBadgeUpdate = (option, value) => {
|
||||
const callback = () => {
|
||||
let newVal = (option==='badgeLabel' && value==='')?'Profile views':value;
|
||||
setBadgeOptions({...badgeOptions, [option]: newVal});
|
||||
props.handleDataChange(option, {target: {value: newVal}})
|
||||
}
|
||||
clearTimeout(debounce);
|
||||
setDebounce(setTimeout(callback, 300));
|
||||
}
|
||||
return (
|
||||
<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">
|
||||
@@ -57,9 +155,20 @@ const Addons = props => {
|
||||
inputId="visitors-count"
|
||||
inputChecked={props.data.visitorsBadge}
|
||||
onInputChange={() => props.handleCheckChange("visitorsBadge")}
|
||||
Icon={ customizeBadgeOpen ? XCircleIcon : ToolsIcon }
|
||||
onIconClick={onCustomizeClick}
|
||||
>
|
||||
display visitors count badge
|
||||
</AddonsItem>
|
||||
{
|
||||
customizeBadgeOpen?
|
||||
<CustomizeBadge
|
||||
githubName={props.social.github}
|
||||
badgeOptions={badgeOptions}
|
||||
onBadgeUpdate={onBadgeUpdate}
|
||||
/>
|
||||
: ''
|
||||
}
|
||||
<AddonsItem
|
||||
inputId="github-profile-trophy"
|
||||
inputChecked={props.data.githubProfileTrophy}
|
||||
|
||||
@@ -80,7 +80,11 @@ const Markdown = props => {
|
||||
return ""
|
||||
}
|
||||
const VisitorsBadge = props => {
|
||||
let link = "https://komarev.com/ghpvc/?username=" + props.github
|
||||
let link = "https://komarev.com/ghpvc/?username="
|
||||
+ props.github
|
||||
+ `&label=${props.badgeOptions.badgeLabel}`
|
||||
+ `&color=${props.badgeOptions.badgeColor}`
|
||||
+ `&style=${props.badgeOptions.badgeStyle}`
|
||||
if (props.show) {
|
||||
return (
|
||||
<>
|
||||
@@ -223,6 +227,11 @@ const Markdown = props => {
|
||||
<VisitorsBadge
|
||||
show={props.data.visitorsBadge}
|
||||
github={props.social.github}
|
||||
badgeOptions={{
|
||||
badgeLabel: encodeURI(props.data.badgeLabel),
|
||||
badgeColor: props.data.badgeColor,
|
||||
badgeStyle: props.data.badgeStyle
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
<>
|
||||
|
||||
@@ -222,7 +222,11 @@ const MarkdownPreview = props => {
|
||||
)
|
||||
}
|
||||
const VisitorsBadgePreview = props => {
|
||||
let link = "https://komarev.com/ghpvc/?username=" + props.github
|
||||
let link = "https://komarev.com/ghpvc/?username="
|
||||
+ props.github
|
||||
+ `&label=${props.badgeOptions.badgeLabel}`
|
||||
+ `&color=${props.badgeOptions.badgeColor}`
|
||||
+ `&style=${props.badgeOptions.badgeStyle}`
|
||||
if (props.show) {
|
||||
return (
|
||||
<div className="text-left my-2">
|
||||
@@ -308,6 +312,11 @@ const MarkdownPreview = props => {
|
||||
<VisitorsBadgePreview
|
||||
show={props.data.visitorsBadge}
|
||||
github={props.social.github}
|
||||
badgeOptions={{
|
||||
badgeLabel: encodeURI(props.data.badgeLabel),
|
||||
badgeColor: props.data.badgeColor,
|
||||
badgeStyle: props.data.badgeStyle
|
||||
}}
|
||||
/>
|
||||
<GithubProfileTrophyPreview
|
||||
show={props.data.githubProfileTrophy}
|
||||
|
||||
+8
-4
@@ -54,6 +54,9 @@ const DEFAULT_DATA = {
|
||||
contact: "",
|
||||
funFact: "",
|
||||
visitorsBadge: false,
|
||||
badgeStyle: "flat",
|
||||
badgeColor: "0e75b6",
|
||||
badgeLabel: "Profile views",
|
||||
githubProfileTrophy: false,
|
||||
githubStats: false,
|
||||
topLanguages: false,
|
||||
@@ -365,10 +368,10 @@ const IndexPage = () => {
|
||||
return
|
||||
}
|
||||
|
||||
setPrefix(cache.prefix || DEFAULT_PREFIX)
|
||||
setData(cache.data || DEFAULT_DATA)
|
||||
setLink(cache.link || DEFAULT_LINK)
|
||||
setSocial(cache.social || DEFAULT_SOCIAL)
|
||||
setPrefix(cache.prefix ? {...DEFAULT_PREFIX, ...cache.prefix} : DEFAULT_PREFIX)
|
||||
setData(cache.data ? {...DEFAULT_DATA, ...cache.data} : DEFAULT_DATA)
|
||||
setLink(cache.link ? {...DEFAULT_LINK, ...cache.link} : DEFAULT_LINK)
|
||||
setSocial(cache.social ? {...DEFAULT_SOCIAL, ...cache.social} : DEFAULT_SOCIAL)
|
||||
|
||||
const cacheSkills = mergeDefaultWithNewDataSkills(
|
||||
DEFAULT_SKILLS,
|
||||
@@ -470,6 +473,7 @@ const IndexPage = () => {
|
||||
data={data}
|
||||
social={social}
|
||||
handleCheckChange={handleCheckChange}
|
||||
handleDataChange={handleDataChange}
|
||||
/>
|
||||
<div className="section">
|
||||
{(data.visitorsBadge ||
|
||||
|
||||
Reference in New Issue
Block a user