diff --git a/web/public/locales/en/translation.json b/web/public/locales/en/translation.json index 0882eb0..0f4f8cd 100644 --- a/web/public/locales/en/translation.json +++ b/web/public/locales/en/translation.json @@ -5,6 +5,7 @@ "providers": { "domains": "Domains", "github": "Github Organization", + "githubSearch": "Github Repository", "npm": "npm", "pypi": "PyPI", "rubygems": "RubyGems", diff --git a/web/public/locales/ja/translation.json b/web/public/locales/ja/translation.json index c0b5dc2..368fac9 100644 --- a/web/public/locales/ja/translation.json +++ b/web/public/locales/ja/translation.json @@ -5,6 +5,7 @@ "providers": { "domains": "ドメイン", "github": "Github Organization", + "githubSearch": "Github リポジトリ", "npm": "npm", "pypi": "PyPI", "rubygems": "RubyGems", diff --git a/web/src/App.js b/web/src/App.js index 07744d0..b7b626d 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -3,18 +3,19 @@ import styled, { createGlobalStyle } from 'styled-components' import { Helmet } from 'react-helmet' import { useTranslation } from 'react-i18next' -import GithubCard from './components/cards/GithubCard' import DomainCard from './components/cards/DomainCard' +import GithubCard from './components/cards/GithubCard' +import NpmCard from './components/cards/NpmCard' +import PypiCard from './components/cards/PypiCard' +import RubyGemsCard from './components/cards/RubyGemsCard' +import CratesioCard from './components/cards/CratesioCard' import HomebrewCard from './components/cards/HomebrewCard' +import LinuxCard from './components/cards/LinuxCard' +import GithubSearchCard from './components/cards/GithubSearchCard' import TwitterCard from './components/cards/TwitterCard' import SlackCard from './components/cards/SlackCard' -import NpmCard from './components/cards/NpmCard' -import JsOrgCard from './components/cards/JsOrgCard' -import PypiCard from './components/cards/PypiCard' import S3Card from './components/cards/S3Card' -import CratesioCard from './components/cards/CratesioCard' -import RubyGemsCard from './components/cards/RubyGemsCard' -import LinuxCard from './components/cards/LinuxCard' +import JsOrgCard from './components/cards/JsOrgCard' import { EventReporter } from './components/Analytics' import Welcome from './components/Welcome' @@ -93,15 +94,16 @@ export default function App() { - - + + + - + diff --git a/web/src/components/Cards.js b/web/src/components/Cards.js index bf5530d..db8f0b9 100644 --- a/web/src/components/Cards.js +++ b/web/src/components/Cards.js @@ -10,8 +10,54 @@ import { Tooltip } from 'react-tippy' import { ExternalLink } from './Links' import 'react-tippy/dist/tippy.css' +export function Card({ title, children }) { + return ( + + {title} + + + + + + }> + {children} + + + + + ) +} + +export function Repeater({ items = [], moreItems = [], children }) { + const [revealAlternatives, setRevealAlternatives] = useState(false) + + function onClick() { + setRevealAlternatives(true) + } + + return ( + <> + {items.map((name) => ( + {children(name)} + ))} + + {revealAlternatives + ? moreItems.map((name) => ( + {children(name)} + )) + : null} + {moreItems.length > 0 && !revealAlternatives ? ( + + ) : null} + + ) +} + export function DedicatedAvailability({ name, + message = '', service, link, prefix = '', @@ -25,19 +71,21 @@ export function DedicatedAvailability({ } return ( - ) } export function ExistentialAvailability({ name, + message = '', target, link, prefix = '', @@ -53,59 +101,54 @@ export function ExistentialAvailability({ const availability = response.status === 404 return ( - ) } -export function CustomSearchCard({ +export const Result = ({ title, - query, + message = '', link, + icon, + color = 'inherit', prefix = '', suffix = '', - icon, - children, -}) { - return ( - - {title} - - {children(query)} - - +}) => { + const content = ( + <> + {prefix} + {title} + {suffix} + ) -} - -export function Card({ title, nameList = [], alternativeList = [], children }) { - const [revealAlternatives, setRevealAlternatives] = useState(false) - - function onClick() { - setRevealAlternatives(true) - } - return ( - - {title} - - {nameList.map((name) => ( - {children(name)} - ))} - {revealAlternatives && - alternativeList.map((name) => ( - {children(name)} - ))} - {alternativeList.length > 0 && !revealAlternatives ? ( - - ) : null} - - + + + + {icon} + + {link ? ( + {content} + ) : ( + content + )} + + + + ) } @@ -141,7 +184,7 @@ class ErrorBoundary extends React.Component { } } -const ErrorHandler = ({ children }) => ( +const CellError = ({ children }) => ( ( ) -const AvailabilityResult = ({ - name, - availability, - link, - prefix = '', - suffix = '', - icon, -}) => ( - - - {icon} - - - {prefix} - {name} - {suffix} - - - - -) - const CardContainer = styled.div` padding: 40px; @@ -195,7 +216,7 @@ const CardTitle = styled.div` } ` -const CardList = styled.div` +const CardContent = styled.div` border-radius: 2px; ${mobile} { diff --git a/web/src/components/cards/CratesioCard.js b/web/src/components/cards/CratesioCard.js index 5df8a8b..33a5b74 100644 --- a/web/src/components/cards/CratesioCard.js +++ b/web/src/components/cards/CratesioCard.js @@ -1,23 +1,27 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { DiRust } from 'react-icons/di' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function CratesioCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/DomainCard.js b/web/src/components/cards/DomainCard.js index 9d0466d..48819a1 100644 --- a/web/src/components/cards/DomainCard.js +++ b/web/src/components/cards/DomainCard.js @@ -1,31 +1,34 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaMapSigns } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function DomainCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [`${lowerCase}.com`, `${lowerCase}app.com`, `${lowerCase}.app`] + const moreNames = [ + `${lowerCase}.dev`, + `${lowerCase}.io`, + `${lowerCase}.tools`, + `get${lowerCase}.com`, + ] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/GithubCard.js b/web/src/components/cards/GithubCard.js index 262583f..61e5b80 100644 --- a/web/src/components/cards/GithubCard.js +++ b/web/src/components/cards/GithubCard.js @@ -1,32 +1,34 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaGithub } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function GithubCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [name] + const moreNames = [ + `${lowerCase}hq`, + `${lowerCase}-team`, + `${lowerCase}-org`, + `${lowerCase}-js`, + ] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/GithubSearchCard.js b/web/src/components/cards/GithubSearchCard.js index d06a394..b13222a 100644 --- a/web/src/components/cards/GithubSearchCard.js +++ b/web/src/components/cards/GithubSearchCard.js @@ -1,26 +1,38 @@ import React from 'react' +import useFetch from 'fetch-suspense' import { useTranslation } from 'react-i18next' import { FaGithub } from 'react-icons/fa' -import fetch from 'isomorphic-unfetch' -import { CustomSearchCard } from '../Cards' -export default function GithubSearchCard({ name }) { +import { Card, Result } from '../Cards' + +function Search({ query }) { + const searchQuery = encodeURIComponent(`${query} in:name`) + const response = useFetch( + `https://api.github.com/search/repositories?q=${searchQuery}&per_page=3` + ) + const repos = response.items + + return ( +
+ {repos.map((repo) => ( + } + key={repo.id} + /> + ))} +
+ ) +} + +export default function GithubSearchCard({ query }) { const { t } = useTranslation() return ( - }> - {async (query) => { - const response = await fetch( - `https://api.github.com/repos/search?q=${query}` - ) - const data = await response.json() - console.log(data) - }} - + + + ) } diff --git a/web/src/components/cards/HomebrewCard.js b/web/src/components/cards/HomebrewCard.js index 57724ec..f280899 100644 --- a/web/src/components/cards/HomebrewCard.js +++ b/web/src/components/cards/HomebrewCard.js @@ -1,32 +1,36 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { IoIosBeer } from 'react-icons/io' -import { Card } from '../Cards' -import { ExistentialAvailability } from '../Cards' + +import { Card, Repeater, ExistentialAvailability } from '../Cards' export default function HomebrewCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + return ( - - {(name) => ( - <> - } - /> - } - /> - - )} + + + {(name) => ( + <> + } + /> + } + /> + + )} + ) } diff --git a/web/src/components/cards/JsOrgCard.js b/web/src/components/cards/JsOrgCard.js index 8abc9f8..f9481a5 100644 --- a/web/src/components/cards/JsOrgCard.js +++ b/web/src/components/cards/JsOrgCard.js @@ -1,23 +1,27 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaJsSquare } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function JsOrgCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/LinuxCard.js b/web/src/components/cards/LinuxCard.js index 1187c52..bac6db3 100644 --- a/web/src/components/cards/LinuxCard.js +++ b/web/src/components/cards/LinuxCard.js @@ -2,33 +2,37 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { DiUbuntu } from 'react-icons/di' import { DiDebian } from 'react-icons/di' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function LinuxCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + return ( - - {(name) => ( - <> - } - /> - } - /> - - )} + + + {(name) => ( + <> + } + /> + } + /> + + )} + ) } diff --git a/web/src/components/cards/NpmCard.js b/web/src/components/cards/NpmCard.js index a5ae537..5224cc6 100644 --- a/web/src/components/cards/NpmCard.js +++ b/web/src/components/cards/NpmCard.js @@ -1,36 +1,38 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaNpm } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function NpmCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + const moreNames = [`${lowerCase}-js`] + return ( - - {(name) => ( - <> - } - /> - } - /> - - )} + + + {(name) => ( + <> + } + /> + } + /> + + )} + ) } diff --git a/web/src/components/cards/PypiCard.js b/web/src/components/cards/PypiCard.js index 9ab7dd2..4d543ac 100644 --- a/web/src/components/cards/PypiCard.js +++ b/web/src/components/cards/PypiCard.js @@ -1,26 +1,28 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaPython } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + import { capitalize } from '../../util/text' +import { Card, DedicatedAvailability, Repeater } from '../Cards' export default function PypiCard({ name }) { const { t } = useTranslation() + const names = [name] + const moreNames = [`Py${capitalize(name)}`] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/RubyGemsCard.js b/web/src/components/cards/RubyGemsCard.js index 7d0b5ee..566b221 100644 --- a/web/src/components/cards/RubyGemsCard.js +++ b/web/src/components/cards/RubyGemsCard.js @@ -1,25 +1,27 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaGem } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function RubyGemsCard({ name }) { const { t } = useTranslation() + const names = [name] + const moreNames = [`${name.toLowerCase()}-rb`] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/S3Card.js b/web/src/components/cards/S3Card.js index d5bc36c..6c32573 100644 --- a/web/src/components/cards/S3Card.js +++ b/web/src/components/cards/S3Card.js @@ -1,24 +1,28 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaAws } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, DedicatedAvailability, Repeater } from '../Cards' export default function S3Card({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/SlackCard.js b/web/src/components/cards/SlackCard.js index 2d222e1..03d28e9 100644 --- a/web/src/components/cards/SlackCard.js +++ b/web/src/components/cards/SlackCard.js @@ -1,24 +1,28 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaSlack } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + +import { Card, DedicatedAvailability, Repeater } from '../Cards' export default function SlackCard({ name }) { const { t } = useTranslation() const lowerCase = name.toLowerCase() + const names = [lowerCase] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) } diff --git a/web/src/components/cards/TwitterCard.js b/web/src/components/cards/TwitterCard.js index c6b4f15..1d32af7 100644 --- a/web/src/components/cards/TwitterCard.js +++ b/web/src/components/cards/TwitterCard.js @@ -1,34 +1,36 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { FaTwitter } from 'react-icons/fa' -import { Card } from '../Cards' -import { DedicatedAvailability } from '../Cards' + import { capitalize } from '../../util/text' +import { Card, Repeater, DedicatedAvailability } from '../Cards' export default function TwitterCard({ name }) { const { t } = useTranslation() + const names = [name] + const moreNames = [ + `${name.toLowerCase()}app`, + `hey${name.toLowerCase()}`, + `${capitalize(name)}Team`, + `${capitalize(name)}HQ`, + `${name.toLowerCase()}_official`, + `${name.toLowerCase()}-support`, + ] + return ( - - {(name) => ( - } - /> - )} + + + {(name) => ( + } + /> + )} + ) }