1
0
mirror of https://github.com/uetchy/namae.git synced 2025-03-17 12:30:32 +09:00

chore: tidy up name list

This commit is contained in:
uetchy 2019-08-01 00:58:44 +09:00
parent 92529201e8
commit 19ffa22c29
4 changed files with 91 additions and 68 deletions

View File

@ -1,40 +1,62 @@
import React from 'react' import React, { Suspense } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import useFetch from 'fetch-suspense' import useFetch from 'fetch-suspense'
import { BarLoader } from 'react-spinners' import { BarLoader } from 'react-spinners'
import { ExternalLink } from './Links' import { ExternalLink } from './Links'
function AvailabilityCell({ class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
return { hasError: true, message: error.message }
}
componentDidCatch(error, info) {}
render() {
if (this.state.hasError) {
return <h4>{this.state.message}</h4>
}
return this.props.children
}
}
const Result = ({
name, name,
availability, availability,
link, link,
prefix = '', prefix = '',
suffix = '', suffix = '',
icon, icon,
}) { }) => (
return ( <Container>
<ItemContainer> <Cell availability={availability}>
{icon} {icon}
<Item> <Name>
<ExternalLink href={link}> <ExternalLink href={link}>
{prefix} {prefix}
{availability ? ( {name}
<span style={{ color: 'green' }}>{name}</span>
) : (
<span style={{ color: 'red' }}>{name}</span>
)}
{suffix} {suffix}
</ExternalLink> </ExternalLink>
</Item> </Name>
</ItemContainer> </Cell>
) </Container>
} )
export const Fallback = () => ( const Fallback = () => (
<ItemContainer> <Container>
<BarLoader /> <BarLoader />
</ItemContainer> </Container>
)
export const AvailabilityContainer = ({ children }) => (
<ErrorBoundary>
<Suspense fallback={<Fallback />}>{children}</Suspense>
</ErrorBoundary>
) )
export function DedicatedAvailability({ export function DedicatedAvailability({
@ -46,11 +68,13 @@ export function DedicatedAvailability({
icon, icon,
}) { }) {
const response = useFetch(`/availability/${service}/${name}`) const response = useFetch(`/availability/${service}/${name}`)
if (response.error) { if (response.error) {
throw new Error(`${service}: ${response.error}`) throw new Error(`${service}: ${response.error}`)
} }
return ( return (
<AvailabilityCell <Result
availability={response.availability} availability={response.availability}
name={name} name={name}
link={link} link={link}
@ -70,12 +94,15 @@ export function ExistentialAvailability({
icon, icon,
}) { }) {
const response = useFetch(target, null, { metadata: true }) const response = useFetch(target, null, { metadata: true })
if (response.status !== 404 && response.status !== 200) { if (response.status !== 404 && response.status !== 200) {
throw new Error(`${name}: ${response.status}`) throw new Error(`${name}: ${response.status}`)
} }
const availability = response.status === 404 const availability = response.status === 404
return ( return (
<AvailabilityCell <Result
name={name} name={name}
availability={availability} availability={availability}
link={link} link={link}
@ -86,16 +113,24 @@ export function ExistentialAvailability({
) )
} }
const ItemContainer = styled.div` const Container = styled.div`
min-height: 1em;
display: flex;
align-items: center;
margin-top: 8px;
`
const Cell = styled.div`
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: flex-start; align-items: flex-start;
margin-top: 8px;
word-break: break-all; word-break: break-all;
color: ${({ availability }) => (availability ? 'green' : 'red')};
` `
const Item = styled.span` const Name = styled.span`
margin-left: 6px; margin-left: 6px;
margin-top: -1px;
font-family: monospace; font-family: monospace;
font-size: 1rem; font-size: 1rem;

View File

@ -1,32 +1,9 @@
import React, { Suspense, useState } from 'react' import React, { useState } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { Fallback } from './Availability' import { AvailabilityContainer } from './Availability'
import { mobile } from '../util/css' import { mobile } from '../util/css'
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
return { hasError: true, message: error.message }
}
componentDidCatch(error, info) {}
render() {
if (this.state.hasError) {
return <h4>{this.state.message}</h4>
}
return this.props.children
}
}
const BoundedSuspense = ({ children }) => (
<ErrorBoundary>
<Suspense fallback={<Fallback />}>{children}</Suspense>
</ErrorBoundary>
)
export function Card({ title, nameList, alternativeList = [], children }) { export function Card({ title, nameList, alternativeList = [], children }) {
const [revealAlternatives, setRevealAlternatives] = useState(false) const [revealAlternatives, setRevealAlternatives] = useState(false)
@ -37,33 +14,30 @@ export function Card({ title, nameList, alternativeList = [], children }) {
return ( return (
<CardWrapper> <CardWrapper>
<CardTitle>{title}</CardTitle> <CardTitle>{title}</CardTitle>
<> <CardList>
{nameList.map((name) => ( {nameList.map((name) => (
<BoundedSuspense>{children(name)}</BoundedSuspense> <AvailabilityContainer>{children(name)}</AvailabilityContainer>
))} ))}
{revealAlternatives && {revealAlternatives &&
alternativeList.map((name) => ( alternativeList.map((name) => (
<BoundedSuspense>{children(name)}</BoundedSuspense> <AvailabilityContainer>{children(name)}</AvailabilityContainer>
))} ))}
</> {alternativeList.length > 0 && !revealAlternatives ? (
{alternativeList.length > 0 && !revealAlternatives ? ( <ShowAlternativesButton onClick={onClick}>
<ShowAlternativesButton onClick={onClick}> show more
show alternatives </ShowAlternativesButton>
</ShowAlternativesButton> ) : null}
) : null} </CardList>
</CardWrapper> </CardWrapper>
) )
} }
const CardWrapper = styled.div` const CardWrapper = styled.div`
margin-bottom: 20px; margin-bottom: 40px;
padding: 40px; padding: 40px;
border-radius: 2px;
${mobile} { ${mobile} {
padding: 20px; padding: 0px;
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
border-radius: 0;
} }
` `
@ -71,6 +45,20 @@ const CardTitle = styled.div`
font-size: 0.8rem; font-size: 0.8rem;
font-weight: bold; font-weight: bold;
margin-bottom: 15px; margin-bottom: 15px;
${mobile} {
padding-left: 20px;
}
`
const CardList = styled.div`
border-radius: 2px;
${mobile} {
padding: 20px;
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
border-radius: 0;
}
` `
const ShowAlternativesButton = styled.div` const ShowAlternativesButton = styled.div`

View File

@ -10,11 +10,12 @@ export default function DomainCard({ name }) {
<Card <Card
title="Domain" title="Domain"
key={lowerCase} key={lowerCase}
nameList={[`${lowerCase}.app`, `${lowerCase}.dev`, `${lowerCase}.org`]} nameList={[`${lowerCase}.com`, `${lowerCase}app.com`, `${lowerCase}.app`]}
alternativeList={[ alternativeList={[
`${lowerCase}app.com`, `${lowerCase}.dev`,
`get${lowerCase}.com`, `${lowerCase}.io`,
`${lowerCase}.build`, `${lowerCase}.build`,
`get${lowerCase}.com`,
]}> ]}>
{(name) => ( {(name) => (
<DedicatedAvailability <DedicatedAvailability

View File

@ -14,15 +14,14 @@ export default function NpmCard({ name }) {
name={name} name={name}
service="npm" service="npm"
link={`https://www.npmjs.com/package/${name}`} link={`https://www.npmjs.com/package/${name}`}
prefix="npmjs.com/"
icon={<FaNpm />} icon={<FaNpm />}
/> />
<DedicatedAvailability <DedicatedAvailability
name={name} name={name}
service="npm-org" service="npm-org"
link={`https://www.npmjs.com/org/${name}`} link={`https://www.npmjs.com/org/${name}`}
prefix="npmjs.com/~" prefix="@"
suffix=" (Org)" suffix=" (Organization)"
icon={<FaNpm />} icon={<FaNpm />}
/> />
</> </>