-
-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor: Moved matchers to a separate dir * chore: Updated getOpenSaucedUser() to return a bool * refactor: Moved injectViewOnOpenSauced to utils * feat: Invite to OS(WIP) * chore: Removed unused listener * chore: Fomatting * chore: Fomatting * chore: Added social icons span * chore: Removed explicit book return and err handling * Update src/components/InviteToOpenSauced/InviteToOpenSaucedModal.ts Co-authored-by: Nick Taylor <[email protected]> * chore: Top level await for getOpenSaucedUser() * chores: Aggregated matchers, updated file-names * chore: createHtmlElement() with added typings * chore: Updated elements to use the new createHtmlElement() * refactor: restructured utilities * chore: remove config imports for now * chore: Improved typing in createHtmlElement() and formatting * chore: Added conditional rendering of social share icons * chore: updated injector functions for empty bio * chore: Updated button-text sizing * chore: Updated LinkedIn share button href * chore: updated null checks * chore: Updated inviteToOS button colors * chore: Update LinkedIn username matcher and modal sizing * Apply copy suggestions from code review * Apply injectViewOnOS rename suggestions from code review * refactor: renamedViewOnOpenSauced() * refactor: updated matcher file name and imports * refactor: Moved the modal display trigger to the component definition * chore: update matchers filename to urlMatchers --------- Co-authored-by: Nick Taylor <[email protected]> Co-authored-by: Brian Douglas <[email protected]>
- Loading branch information
1 parent
d19034d
commit 0c8f222
Showing
14 changed files
with
236 additions
and
42 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions
20
src/components/InviteToOpenSauced/InviteToOpenSaucedButton.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import logoIcon from "../../assets/opensauced-icon.svg"; | ||
import "../../index.css"; | ||
import { createHtmlElement } from "../../utils/createHtmlElement"; | ||
|
||
export const InviteToOpenSaucedButton = () => { | ||
const inviteToOpenSaucedButton = createHtmlElement("a", { | ||
className: | ||
"inline-block mt-4 text-white rounded-md p-2 text-sm font-semibold text-center select-none w-full border border-solid cursor-pointer bg-gh-gray hover:bg-red-500 hover:shadow-button hover:no-underline", | ||
innerHTML: `<img | ||
class="mx-2 inline-block align-top" | ||
src="${chrome.runtime.getURL(logoIcon)}" | ||
alt="OpenSauced Logo" | ||
width="20" | ||
height="20" | ||
/> | ||
<span>Invite to OpenSauced</span> | ||
`, | ||
}); | ||
return inviteToOpenSaucedButton; | ||
}; |
97 changes: 97 additions & 0 deletions
97
src/components/InviteToOpenSauced/InviteToOpenSaucedModal.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import "../../index.css"; | ||
import { createHtmlElement } from "../../utils/createHtmlElement"; | ||
import emailSocialIcon from "../../assets/mail-icon.svg"; | ||
import twitterSocialIcon from "../../assets/twitter-icon.svg"; | ||
import linkedInSocailIcon from "../../assets/linkedin-icon.svg"; | ||
|
||
interface Socials { | ||
emailAddress?: string; | ||
twitterUsername?: string; | ||
linkedInUsername?: string; | ||
} | ||
|
||
export const InviteToOpenSaucedModal = ( | ||
username: string, | ||
{ emailAddress, twitterUsername, linkedInUsername }: Socials = {}, modalDisplayTrigger?: HTMLElement | ||
) => { | ||
const emailBody = | ||
typeof emailAddress === "string" && | ||
`Hey ${username}. I'm using OpenSauced to keep track of your contributions and discover new projects. Check it out at https://hot.opensauced.pizza/`; | ||
const emailHref = | ||
typeof emailAddress === "string" && | ||
`mailto:${emailAddress}?subject=${encodeURIComponent( | ||
"Invitation to join OpenSauced!" | ||
)}&body=${encodeURIComponent(emailBody)}`; | ||
const tweetHref = | ||
typeof twitterUsername === "string" && | ||
`https://twitter.com/intent/tweet?text=${encodeURIComponent( | ||
`Check out @saucedopen. The platform for open source contributors to find their next contribution. https://opensauced.pizza/blog/social-coding-is-back. @${twitterUsername}` | ||
)}&hashtags=opensource,github`; | ||
const linkedinHref = | ||
typeof linkedInUsername === "string" && | ||
`https://www.linkedin.com/in/${linkedInUsername}`; | ||
|
||
const emailIcon = emailBody | ||
? createHtmlElement("a", { | ||
href: emailHref, | ||
innerHTML: `<img src=${chrome.runtime.getURL( | ||
emailSocialIcon | ||
)} alt="Email">`, | ||
}) | ||
: ""; | ||
const twitterIcon = tweetHref | ||
? createHtmlElement("a", { | ||
href: tweetHref, | ||
innerHTML: `<img src=${chrome.runtime.getURL( | ||
twitterSocialIcon | ||
)} alt="Twitter">`, | ||
}) | ||
: ""; | ||
const linkedInIcon = linkedinHref | ||
? createHtmlElement("a", { | ||
href: linkedinHref, | ||
innerHTML: `<img src=${chrome.runtime.getURL( | ||
linkedInSocailIcon | ||
)} alt="LinkedIn">`, | ||
}) | ||
: ""; | ||
|
||
const socialIcons = createHtmlElement("span", { | ||
className: "flex flex-nowrap space-x-3", | ||
}); | ||
|
||
const inviteToOpenSaucedModal = createHtmlElement("div", { | ||
className: | ||
"fixed h-full w-full z-50 bg-gray-600 bg-opacity-50 overflow-y-auto inset-0", | ||
style: { display: "none" }, | ||
id: "invite-modal", | ||
}); | ||
|
||
const inviteToOpenSaucedModalContainer = createHtmlElement("div", { | ||
className: | ||
"mt-2 min-w-[33%] relative top-60 mx-auto p-4 border w-96 rounded-md shadow-button border-solid border-orange bg-slate-800", | ||
innerHTML: ` | ||
<h3 class="text-2xl leading-6 font-bold">Invite ${username} to <a href="https://hot.opensauced.pizza/"><span class="hover:text-orange hover:underline">OpenSauced!</span></a></h3> | ||
<div class="mt-2"> | ||
<p class="text-md"> | ||
Use the links below to invite them. | ||
</p> | ||
</div> | ||
`, | ||
}); | ||
|
||
inviteToOpenSaucedModal.onclick = (e) => { | ||
if (e.target === inviteToOpenSaucedModal) | ||
inviteToOpenSaucedModal.style.display = "none"; | ||
}; | ||
|
||
if (modalDisplayTrigger) modalDisplayTrigger.onclick = () => { | ||
inviteToOpenSaucedModal.style.display = "block"; | ||
}; | ||
|
||
socialIcons.replaceChildren(emailIcon, twitterIcon, linkedInIcon); | ||
inviteToOpenSaucedModalContainer.appendChild(socialIcons); | ||
inviteToOpenSaucedModal.appendChild(inviteToOpenSaucedModalContainer); | ||
|
||
return inviteToOpenSaucedModal; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,11 @@ | ||
import { getGithubUsername } from "../utils/getDetailsFromGithubUrl"; | ||
import { getGithubUsername } from "../utils/urlMatchers"; | ||
import { getOpenSaucedUser } from "../utils/fetchOpenSaucedApiData"; | ||
import { ViewOnOpenSaucedButton } from "../components/ViewOnOpenSaucedButton/ViewOnOpenSaucedButton"; | ||
|
||
function injectViewOnOpenSaucedButton() { | ||
const username = getGithubUsername(window.location.href); | ||
if (!username) { | ||
return; | ||
} | ||
|
||
const openSaucedUser = getOpenSaucedUser(username); | ||
if (!openSaucedUser) { | ||
return; | ||
} | ||
|
||
const viewOnOpenSaucedButton = ViewOnOpenSaucedButton(username); | ||
|
||
const userBio = document.querySelector(".p-note.user-profile-bio"); | ||
if (!userBio) { | ||
return; | ||
} | ||
userBio.appendChild(viewOnOpenSaucedButton); | ||
import injectViewOnOpenSauced from "../utils/dom-utils/viewOnOpenSauced"; | ||
import injectInviteToOpenSauced from "../utils/dom-utils/inviteToOpenSauced"; | ||
|
||
const username = getGithubUsername(window.location.href); | ||
if (username != null) { | ||
const openSaucedUser = await getOpenSaucedUser(username); | ||
if (openSaucedUser) injectViewOnOpenSauced(username); | ||
else injectInviteToOpenSauced(username); | ||
} | ||
|
||
injectViewOnOpenSaucedButton(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { CSSProperties } from "react"; | ||
|
||
type ElementProps = { | ||
style?: CSSProperties; | ||
[key: string]: any; | ||
}; | ||
|
||
type CssDeclaration = keyof Omit<CSSStyleDeclaration, "length" | "parentRule">; | ||
|
||
export function createHtmlElement<T extends keyof HTMLElementTagNameMap>( | ||
nodeName: T, | ||
props: ElementProps | ||
) { | ||
const { style, ...nonStyleProps } = props; | ||
const element = Object.assign(document.createElement(nodeName), props); | ||
if (style != undefined) | ||
Object.entries(style).forEach(([key, value]) => { | ||
element.style[key as CssDeclaration] = value; | ||
}); | ||
return element; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { InviteToOpenSaucedButton } from "../../components/InviteToOpenSauced/InviteToOpenSaucedButton"; | ||
import { InviteToOpenSaucedModal } from "../../components/InviteToOpenSauced/InviteToOpenSaucedModal"; | ||
import { getTwitterUsername, getLinkedInUsername } from "../urlMatchers"; | ||
|
||
const injectOpenSaucedInviteButton = (username: string) => { | ||
const emailAddress: string | undefined = ( | ||
document.querySelector(`a[href^="mailto:"]`) as HTMLAnchorElement | ||
)?.href.substr(7); | ||
const twitterUrl: string | undefined = ( | ||
document.querySelector(`a[href*="twitter.com"]`) as HTMLAnchorElement | ||
)?.href; | ||
const linkedInUrl: string | undefined = ( | ||
document.querySelector(`a[href*="linkedin.com"]`) as HTMLAnchorElement | ||
)?.href; | ||
if (!(emailAddress || twitterUrl || linkedInUrl)) return; | ||
|
||
const twitterUsername = twitterUrl && getTwitterUsername(twitterUrl); | ||
const linkedInUsername = linkedInUrl && getLinkedInUsername(linkedInUrl); | ||
const inviteToOpenSaucedButton = InviteToOpenSaucedButton(); | ||
const inviteToOpenSaucedModal = InviteToOpenSaucedModal(username, { | ||
emailAddress, | ||
twitterUsername, | ||
linkedInUsername, | ||
}, inviteToOpenSaucedButton); | ||
|
||
const userBio = document.querySelector(".p-nickname.vcard-username.d-block"); | ||
if (!userBio || !userBio.parentNode) return; | ||
userBio.parentNode.replaceChild(inviteToOpenSaucedButton, userBio); | ||
document.body.appendChild(inviteToOpenSaucedModal); | ||
}; | ||
|
||
export default injectOpenSaucedInviteButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { ViewOnOpenSaucedButton } from "../../components/ViewOnOpenSaucedButton/ViewOnOpenSaucedButton"; | ||
|
||
const injectViewOnOpenSaucedButton = (username: string) => { | ||
const viewOnOpenSaucedButton = ViewOnOpenSaucedButton(username); | ||
|
||
const userBio = document.querySelector( | ||
".p-nickname.vcard-username.d-block, button.js-profile-editable-edit-button" | ||
); | ||
if (!userBio || !userBio.parentNode) return; | ||
userBio.parentNode.replaceChild(viewOnOpenSaucedButton, userBio); | ||
}; | ||
|
||
export default injectViewOnOpenSaucedButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export const getGithubUsername = (url: string) => { | ||
const match = url.match(/github\.com\/([^/]+)/); | ||
return match && match[1]; | ||
}; | ||
|
||
export const getLinkedInUsername = (url: string) => { | ||
const match = url.match( | ||
/(?:https?:\/\/)?(?:www\.)?linkedin\.com\/in\/(?:#!\/)?@?([^\/\?\s]*)/ | ||
); | ||
return match ? match[1] : undefined; | ||
}; | ||
|
||
export const getTwitterUsername = (url: string) => { | ||
const match = url.match( | ||
/(?:https?:\/\/)?(?:www\.)?twitter\.com\/(?:#!\/)?@?([^\/\?\s]*)/ | ||
); | ||
return match ? match[1] : undefined; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters