app tiles
This commit is contained in:
parent
363a82a845
commit
1a71656508
|
|
@ -63,7 +63,7 @@ export function DashboardLanding({ render }: { render: () => void }) {
|
|||
</TabBar>
|
||||
|
||||
<TabContent active={dashboardTab === 'urls' || undefined}>
|
||||
<Urls />
|
||||
<Urls render={render} />
|
||||
</TabContent>
|
||||
|
||||
<TabContent active={dashboardTab === 'logs' || undefined}>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import { buildAppUrl } from '../../shared/urls'
|
||||
import { apps } from '../state'
|
||||
import { apps, setSelectedApp } from '../state'
|
||||
import {
|
||||
EmptyState,
|
||||
StatusDot,
|
||||
UrlLeft,
|
||||
UrlLink,
|
||||
UrlList,
|
||||
UrlPort,
|
||||
UrlRow,
|
||||
Tile,
|
||||
TileGrid,
|
||||
TileIcon,
|
||||
TileName,
|
||||
TilePort,
|
||||
TileStatus,
|
||||
} from '../styles'
|
||||
|
||||
export function Urls() {
|
||||
export function Urls({ render }: { render: () => void }) {
|
||||
const nonTools = apps.filter(a => !a.tool)
|
||||
|
||||
if (nonTools.length === 0) {
|
||||
|
|
@ -18,26 +18,32 @@ export function Urls() {
|
|||
}
|
||||
|
||||
return (
|
||||
<UrlList>
|
||||
<TileGrid>
|
||||
{nonTools.map(app => {
|
||||
const url = buildAppUrl(app.name, location.origin)
|
||||
const running = app.state === 'running'
|
||||
|
||||
const openAppPage = (e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
setSelectedApp(app.name)
|
||||
render()
|
||||
}
|
||||
|
||||
return (
|
||||
<UrlRow key={app.name}>
|
||||
<UrlLeft>
|
||||
<StatusDot state={app.state} />
|
||||
<span>{app.icon}</span>
|
||||
{running ? (
|
||||
<UrlLink href={url} target="_blank">{url}</UrlLink>
|
||||
) : (
|
||||
<span style={{ color: 'var(--colors-textFaint)' }}>{app.name}</span>
|
||||
)}
|
||||
</UrlLeft>
|
||||
{app.port ? <UrlPort>:{app.port}</UrlPort> : null}
|
||||
</UrlRow>
|
||||
<Tile
|
||||
key={app.name}
|
||||
href={running ? url : undefined}
|
||||
target={running ? '_blank' : undefined}
|
||||
style={running ? undefined : { cursor: 'default' }}
|
||||
>
|
||||
<TileStatus state={app.state} onClick={openAppPage} />
|
||||
<TileIcon>{app.icon}</TileIcon>
|
||||
<TileName>{app.name}</TileName>
|
||||
<TilePort>{app.port ? `:${app.port}` : '\u2014'}</TilePort>
|
||||
</Tile>
|
||||
)
|
||||
})}
|
||||
</UrlList>
|
||||
</TileGrid>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,58 +203,73 @@ export const LogStatus = define('LogStatus', {
|
|||
},
|
||||
})
|
||||
|
||||
// URL List
|
||||
export const UrlLeft = define('UrlLeft', {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
minWidth: 0,
|
||||
})
|
||||
|
||||
export const UrlLink = define('UrlLink', {
|
||||
base: 'a',
|
||||
color: theme('colors-link'),
|
||||
textDecoration: 'none',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
selectors: {
|
||||
'&:hover': { textDecoration: 'underline' },
|
||||
},
|
||||
})
|
||||
|
||||
export const UrlList = define('UrlList', {
|
||||
// App Tiles Grid
|
||||
export const TileGrid = define('TileGrid', {
|
||||
width: '100%',
|
||||
minWidth: 400,
|
||||
maxWidth: 800,
|
||||
maxWidth: 900,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))',
|
||||
gap: 20,
|
||||
})
|
||||
|
||||
export const Tile = define('Tile', {
|
||||
base: 'a',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
padding: '28px 20px 24px',
|
||||
background: theme('colors-bgElement'),
|
||||
border: `1px solid ${theme('colors-border')}`,
|
||||
borderRadius: theme('radius-md'),
|
||||
overflow: 'hidden',
|
||||
})
|
||||
|
||||
export const UrlPort = define('UrlPort', {
|
||||
fontFamily: theme('fonts-mono'),
|
||||
fontSize: 12,
|
||||
color: theme('colors-textFaint'),
|
||||
flexShrink: 0,
|
||||
})
|
||||
|
||||
export const UrlRow = define('UrlRow', {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: '10px 16px',
|
||||
fontFamily: theme('fonts-mono'),
|
||||
fontSize: 13,
|
||||
textDecoration: 'none',
|
||||
cursor: 'pointer',
|
||||
selectors: {
|
||||
'&:hover': {
|
||||
background: theme('colors-bgHover'),
|
||||
},
|
||||
'&:not(:last-child)': {
|
||||
borderBottom: `1px solid ${theme('colors-border')}`,
|
||||
borderColor: theme('colors-textFaint'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const TileIcon = define('TileIcon', {
|
||||
fontSize: 48,
|
||||
lineHeight: 1,
|
||||
userSelect: 'none',
|
||||
})
|
||||
|
||||
export const TileName = define('TileName', {
|
||||
fontSize: 15,
|
||||
fontWeight: 600,
|
||||
color: theme('colors-text'),
|
||||
textAlign: 'center',
|
||||
})
|
||||
|
||||
export const TilePort = define('TilePort', {
|
||||
fontFamily: theme('fonts-mono'),
|
||||
fontSize: 13,
|
||||
color: theme('colors-textFaint'),
|
||||
})
|
||||
|
||||
export const TileStatus = define('TileStatus', {
|
||||
position: 'absolute',
|
||||
top: 8,
|
||||
right: 8,
|
||||
width: 2,
|
||||
height: 2,
|
||||
borderRadius: '50%',
|
||||
cursor: 'pointer',
|
||||
padding: 4,
|
||||
backgroundClip: 'content-box',
|
||||
variants: {
|
||||
state: {
|
||||
error: { background: theme('colors-statusInvalid') },
|
||||
invalid: { background: theme('colors-statusInvalid') },
|
||||
stopped: { background: theme('colors-statusStopped') },
|
||||
starting: { background: theme('colors-statusStarting') },
|
||||
running: { background: theme('colors-statusRunning') },
|
||||
stopping: { background: theme('colors-statusStarting') },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -15,11 +15,12 @@ export {
|
|||
LogStatus,
|
||||
LogText,
|
||||
LogTimestamp,
|
||||
UrlLeft,
|
||||
UrlLink,
|
||||
UrlList,
|
||||
UrlPort,
|
||||
UrlRow,
|
||||
Tile,
|
||||
TileGrid,
|
||||
TileIcon,
|
||||
TileName,
|
||||
TilePort,
|
||||
TileStatus,
|
||||
VitalCard,
|
||||
VitalLabel,
|
||||
VitalsSection,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user