finishing touches on new version
This commit is contained in:
parent
7c5f32d835
commit
c17b40c723
30
index.html
30
index.html
@ -7,7 +7,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="The Para-Real: Finding the Future in Unexpected Places - A livestream series about subcultures building livelihoods in spite of platform exploitation."
|
content="Quality live programming from beyond the surveillance economy.."
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
@ -25,32 +25,26 @@
|
|||||||
<link rel="mask-icon" href="static/safari-pinned-tab.svg" color="#5bbad5" />
|
<link rel="mask-icon" href="static/safari-pinned-tab.svg" color="#5bbad5" />
|
||||||
<meta name="msapplication-TileColor" content="#da532c" />
|
<meta name="msapplication-TileColor" content="#da532c" />
|
||||||
<meta name="theme-color" content="#ffffff" />
|
<meta name="theme-color" content="#ffffff" />
|
||||||
<meta
|
<meta content="Underscore Streams" property="og:site_name" />
|
||||||
content="The Para-Real: Finding the Future in Unexpected Places"
|
|
||||||
property="og:site_name"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary" />
|
<meta name="twitter:card" content="summary" />
|
||||||
<meta
|
<meta name="twitter:title" content="Underscore Streams" />
|
||||||
name="twitter:title"
|
|
||||||
content="The Para-Real: Finding the Future in Unexpected Places"
|
|
||||||
/>
|
|
||||||
<meta
|
<meta
|
||||||
name="twitter:description"
|
name="twitter:description"
|
||||||
content="The NEW DESIGN CONGRESS x RECLAIMFUTURES present a livestream series about subcultures building livelihoods in spite of platform exploitation."
|
content="Quality live programming from beyond the surveillance economy."
|
||||||
/>
|
/>
|
||||||
<meta name="twitter:image" content="https://i.ibb.co/vcyKrKw/twitter.jpg" />
|
<meta name="twitter:image" content="https://i.ibb.co/vcyKrKw/twitter.jpg" />
|
||||||
|
|
||||||
<meta
|
<meta property="og:title" content="Underscore Streams" />
|
||||||
property="og:title"
|
|
||||||
content="The Para-Real: Finding the Future in Unexpected Places"
|
|
||||||
/>
|
|
||||||
<meta
|
<meta
|
||||||
property="og:description"
|
property="og:description"
|
||||||
content="The NEW DESIGN CONGRESS x RECLAIMFUTURES present a livestream series about subcultures building livelihoods in spite of platform exploitation"
|
content="Quality live programming from beyond the surveillance economy."
|
||||||
/>
|
/>
|
||||||
<meta property="og:image" content="static/meta.png" />
|
<meta
|
||||||
<meta property="og:url" content="https://stream.undersco.re/" />
|
property="og:image"
|
||||||
|
content="https://stream.underscore/static/meta.png"
|
||||||
|
/>
|
||||||
|
<meta property="og:url" content="https://stream.underscore/" />
|
||||||
|
|
||||||
<link rel="stylesheet" href="./src/assets/styles/index.scss" />
|
<link rel="stylesheet" href="./src/assets/styles/index.scss" />
|
||||||
</head>
|
</head>
|
||||||
@ -64,7 +58,7 @@
|
|||||||
_paq.push(['trackPageView'])
|
_paq.push(['trackPageView'])
|
||||||
_paq.push(['enableLinkTracking'])
|
_paq.push(['enableLinkTracking'])
|
||||||
;(function() {
|
;(function() {
|
||||||
var u = 'https://data.undersco.re/'
|
var u = 'https://data.underscore/'
|
||||||
_paq.push(['setTrackerUrl', u + 'matomo.php'])
|
_paq.push(['setTrackerUrl', u + 'matomo.php'])
|
||||||
_paq.push(['setSiteId', '5'])
|
_paq.push(['setSiteId', '5'])
|
||||||
var d = document,
|
var d = document,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "yarn parcel index.html",
|
"start": "yarn parcel index.html",
|
||||||
"dev": "yarn parcel watch index.html",
|
"dev": "yarn parcel watch index.html",
|
||||||
"build": "yarn parcel build index.js",
|
"build": "yarn parcel build index.js && cp -r static dist/static",
|
||||||
"deploy": "yarn parcel build; rsync rsync -aP ./dist/ inu@95.216.203.71:/media/www/stream.undersco.re/"
|
"deploy": "yarn parcel build; rsync rsync -aP ./dist/ inu@95.216.203.71:/media/www/stream.undersco.re/"
|
||||||
},
|
},
|
||||||
"alias": {
|
"alias": {
|
||||||
@ -21,6 +21,7 @@
|
|||||||
"date-fns-tz": "^1.1.4",
|
"date-fns-tz": "^1.1.4",
|
||||||
"datebook": "^7.0.7",
|
"datebook": "^7.0.7",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
|
"he": "^1.2.0",
|
||||||
"ical": "^0.8.0",
|
"ical": "^0.8.0",
|
||||||
"ical.js": "^1.4.0",
|
"ical.js": "^1.4.0",
|
||||||
"markdown-to-jsx": "^7.1.2",
|
"markdown-to-jsx": "^7.1.2",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 594 KiB |
@ -1,5 +1,6 @@
|
|||||||
/* eslint-disable jsx-a11y/anchor-has-content */
|
/* eslint-disable jsx-a11y/anchor-has-content */
|
||||||
import { h, Fragment } from 'preact'
|
import { h, Fragment } from 'preact'
|
||||||
|
import { decode } from 'he'
|
||||||
import MarkdownRenderer from 'markdown-to-jsx'
|
import MarkdownRenderer from 'markdown-to-jsx'
|
||||||
import { MarkdownWrapper } from './styles'
|
import { MarkdownWrapper } from './styles'
|
||||||
import { P, A, H1, H2, H3, Span } from '../Text'
|
import { P, A, H1, H2, H3, Span } from '../Text'
|
||||||
@ -44,7 +45,7 @@ const Markdown = ({ children, withLinebreaks, options, theme, ...rest }) => (
|
|||||||
}}
|
}}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{decode(children)}
|
||||||
</MarkdownRenderer>
|
</MarkdownRenderer>
|
||||||
</MarkdownWrapper>
|
</MarkdownWrapper>
|
||||||
)
|
)
|
||||||
|
@ -9,7 +9,7 @@ export const MarkdownWrapper = styled.span`
|
|||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 200px;
|
max-width: 300px;
|
||||||
float: left;
|
float: left;
|
||||||
padding: 0 12px 6px 0;
|
padding: 0 12px 6px 0;
|
||||||
}
|
}
|
||||||
@ -22,6 +22,10 @@ export const MarkdownWrapper = styled.span`
|
|||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 1em 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-bottom: ${props => (props.$withLinebreaks ? '32px' : '0')};
|
margin-bottom: ${props => (props.$withLinebreaks ? '32px' : '0')};
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,19 @@ import { Img, LabelBlock, Wrapper } from './styles'
|
|||||||
import { andList } from '../../helpers/string'
|
import { andList } from '../../helpers/string'
|
||||||
import { colours } from '../../assets/theme'
|
import { colours } from '../../assets/theme'
|
||||||
|
|
||||||
const SeriesCard = ({ series: { image, episodes: allEpisodes, title, subtitle, hosts: hostsArray, slug, }, isPast, ...rest }) => {
|
const SeriesCard = ({ series: { image, episodes, title, subtitle, hosts: hostsArray, slug, }, isPast, ...rest }) => {
|
||||||
const episodes = allEpisodes[isPast ? 'past' : 'future']
|
|
||||||
const hosts = hostsArray.map(({ actor }) => actor.name)
|
const hosts = hostsArray.map(({ actor }) => actor.name)
|
||||||
|
|
||||||
// return episodes.length ? (
|
const episodesLength = episodes.past.length + episodes.future.length
|
||||||
|
|
||||||
|
const getNextLastStreamText = () => {
|
||||||
|
const hasFutureEpisodes = episodes.future.length
|
||||||
|
const prefix = hasFutureEpisodes ? strings.en.nextStream : strings.en.lastStream
|
||||||
|
const mainText = formatDistanceToNow(new Date(episodes[hasFutureEpisodes ? 'future' : 'past'][0][hasFutureEpisodes ? 'endsOn' : 'beginsOn']), { addSuffix: true })
|
||||||
|
|
||||||
|
return `${prefix} ${mainText}`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={`series/${slug}`}>
|
<Link to={`series/${slug}`}>
|
||||||
<Wrapper {...rest}>
|
<Wrapper {...rest}>
|
||||||
@ -19,12 +27,12 @@ const SeriesCard = ({ series: { image, episodes: allEpisodes, title, subtitle, h
|
|||||||
<LabelBlock
|
<LabelBlock
|
||||||
$position="top"
|
$position="top"
|
||||||
>
|
>
|
||||||
{episodes.length} {episodes.length === 1 ? strings.en.episode : strings.en.episodes}
|
{episodesLength} {episodesLength === 1 ? strings.en.episode : strings.en.episodes}
|
||||||
</LabelBlock>
|
</LabelBlock>
|
||||||
<LabelBlock
|
<LabelBlock
|
||||||
$position="bottom"
|
$position="bottom"
|
||||||
>
|
>
|
||||||
{isPast ? strings.en.lastStream : strings.en.nextStream} {episodes && episodes.length && formatDistanceToNow(new Date(episodes[0][isPast ? 'endsOn' : 'beginsOn']), { addSuffix: true })}
|
{getNextLastStreamText()}
|
||||||
</LabelBlock>
|
</LabelBlock>
|
||||||
</Img>
|
</Img>
|
||||||
|
|
||||||
@ -34,7 +42,6 @@ const SeriesCard = ({ series: { image, episodes: allEpisodes, title, subtitle, h
|
|||||||
</Wrapper>
|
</Wrapper>
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
// ) : null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SeriesCard
|
export default SeriesCard
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
peertube_root: 'https://tv.undersco.re',
|
peertube_root: 'https://tv.undersco.re',
|
||||||
EVENTS_API_URL: 'http://localhost:3031',
|
EVENTS_API_URL: 'https://api.undersco.re',
|
||||||
seriesTrailerId: 'b-JQ5Bo4JnI',
|
|
||||||
|
|
||||||
calendarId: 'Nt767W2KeKFSTZ8x',
|
calendarId: 'Nt767W2KeKFSTZ8x',
|
||||||
chat: {
|
chat: {
|
||||||
|
@ -10,7 +10,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Archive',
|
label: 'Archive',
|
||||||
href: 'https://tv.undersco.re/'
|
href: 'https://tv.undersco.re/search?sort=-match&searchTarget=local&search=livestream'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
export const slugify = (title) => {
|
export const slugify = (title) => {
|
||||||
let str = title ? title.replace(/^\s+|\s+$/g, '') : null // trim
|
let str = title ? title.replace(/^\s+|\s+$/g, '') : null // trim
|
||||||
|
|
||||||
if (!str) return title;
|
if (!str) return title
|
||||||
|
|
||||||
str = str.toLowerCase()
|
str = str.toLowerCase()
|
||||||
|
|
||||||
@ -22,15 +22,11 @@ export const slugify = (title) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const capitaliseFirstLetter = word =>
|
export const capitaliseFirstLetter = word =>
|
||||||
word ? `${word?.charAt(0).toUpperCase()}${word?.slice(1)}` : '';
|
word ? `${word.charAt(0).toUpperCase()}${word.slice(1)}` : word
|
||||||
|
|
||||||
export const camelise = str => {
|
export const camelise = str => str ? str
|
||||||
return str ? str
|
.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => index === 0 ? letter.toLowerCase() : letter.toUpperCase())
|
||||||
.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
|
.replace(/\s+/g, '') : str
|
||||||
return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
|
|
||||||
})
|
|
||||||
.replace(/\s+/g, '') : str
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -45,23 +41,23 @@ export const camelise = str => {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export const andList = (list, connector = '&', wrapEachItem, replace = '{#}') => {
|
export const andList = (list, connector = '&', wrapEachItem, replace = '{#}') => {
|
||||||
if (!Array.isArray(list)) return list;
|
if (!Array.isArray(list)) return list
|
||||||
|
|
||||||
const wrapItem = (item) => {
|
const wrapItem = (item) => {
|
||||||
if (wrapEachItem) {
|
if (wrapEachItem) {
|
||||||
if (Array.isArray(item)) {
|
if (Array.isArray(item)) {
|
||||||
return `${wrapEachItem.before.replace(replace, item[1])}${item[0]}${wrapEachItem.after.replace(replace, item[1])}`;
|
return `${wrapEachItem.before.replace(replace, item[1])}${item[0]}${wrapEachItem.after.replace(replace, item[1])}`
|
||||||
}
|
}
|
||||||
return `${wrapEachItem.before}${item}${wrapEachItem.after}`;
|
return `${wrapEachItem.before}${item}${wrapEachItem.after}`
|
||||||
}
|
}
|
||||||
return item;
|
return item
|
||||||
};
|
}
|
||||||
|
|
||||||
return list.map((item, index) => {
|
return list.map((item, index) => {
|
||||||
if (index + 1 === list.length && index !== 0) {
|
if (index + 1 === list.length && index !== 0) {
|
||||||
return ` ${connector} ${wrapItem(item)}`;
|
return ` ${connector} ${wrapItem(item)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.length === 1 || index === list.length - 2 ? wrapItem(item) : `${wrapItem(item)}, `;
|
return list.length === 1 || index === list.length - 2 ? wrapItem(item) : `${wrapItem(item)}, `
|
||||||
}).join('');
|
}).join('')
|
||||||
};
|
}
|
@ -61,7 +61,7 @@ export const Hero = styled.div`
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: url(${(props) => props.image});
|
background: url(${(props) => props.image});
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position-x: right;
|
background-position-x: center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -86,7 +86,7 @@ export const Hero = styled.div`
|
|||||||
font-size: 9vw;
|
font-size: 9vw;
|
||||||
}
|
}
|
||||||
@media screen and (min-width: ${screenSizes.lg}px) {
|
@media screen and (min-width: ${screenSizes.lg}px) {
|
||||||
font-size: 14vw;
|
font-size: 12vw;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ export const SeriesGrid = styled.div`
|
|||||||
export const ScheduleList = styled.ul`
|
export const ScheduleList = styled.ul`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const Day = styled.div`
|
export const Day = styled.div`
|
||||||
@ -38,6 +39,8 @@ export const Content = styled.div`
|
|||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollbar-width: none;
|
||||||
`
|
`
|
||||||
/* ${mediaQuery.lessThan('lg')`
|
/* ${mediaQuery.lessThan('lg')`
|
||||||
max-height: calc(100vh - 200px);
|
max-height: calc(100vh - 200px);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable react/prop-types */
|
/* eslint-disable react/prop-types */
|
||||||
import { isWithinInterval } from 'date-fns'
|
import { addYears, isFuture } from 'date-fns'
|
||||||
import { Fragment, h } from 'preact'
|
import { Fragment, h } from 'preact'
|
||||||
import { H1, H2 } from '../../components/Text'
|
import { H1, H2 } from '../../components/Text'
|
||||||
import strings from '../../data/strings'
|
import strings from '../../data/strings'
|
||||||
@ -15,34 +15,40 @@ const Series = () => {
|
|||||||
const pastSeries = []
|
const pastSeries = []
|
||||||
|
|
||||||
const currentSeries = data.series ? data.series.filter(series => {
|
const currentSeries = data.series ? data.series.filter(series => {
|
||||||
// const seriesInTheLastMonth = series.episodes.past.filter(episode => {
|
|
||||||
// })
|
|
||||||
if (series.episodes.future.length) {
|
if (series.episodes.future.length) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (series.episodes.past.every(({ beginsOn }) => isFuture(addYears(new Date(beginsOn), 1)))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
pastSeries.push(series)
|
pastSeries.push(series)
|
||||||
return false
|
return false
|
||||||
}) : []
|
}) : []
|
||||||
|
|
||||||
|
console.log({ currentSeries })
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title={strings.en.series}>
|
<Page title={strings.en.series}>
|
||||||
<Content>
|
<Content>
|
||||||
{currentSeries.map(series => (
|
<Fragment>
|
||||||
<Fragment>
|
<Title colour={colours.rose}>{strings.en.currentSeries}</Title>
|
||||||
<Title colour={colours.rose}>{strings.en.currentSeries}</Title>
|
<SeriesGrid>
|
||||||
<SeriesGrid>
|
{currentSeries.reverse().map(series => (
|
||||||
<SeriesCard series={series} />
|
<SeriesCard series={series} />
|
||||||
|
))}
|
||||||
|
</SeriesGrid>
|
||||||
|
</Fragment>
|
||||||
|
{pastSeries.length ? (
|
||||||
|
<Fragment>
|
||||||
|
<Title colour={colours.rose}>{strings.en.pastSeries}</Title>
|
||||||
|
<SeriesGrid>
|
||||||
|
{pastSeries.map(series => (
|
||||||
|
<SeriesCard series={series} isPast />
|
||||||
|
))}
|
||||||
</SeriesGrid>
|
</SeriesGrid>
|
||||||
</Fragment>
|
</Fragment>) : null}
|
||||||
))}
|
|
||||||
<Title colour={colours.rose}>{strings.en.pastSeries}</Title>
|
|
||||||
<SeriesGrid>
|
|
||||||
{pastSeries.map(series => (
|
|
||||||
<SeriesCard series={series} isPast />
|
|
||||||
))}
|
|
||||||
</SeriesGrid>
|
|
||||||
</Content>
|
</Content>
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
@ -16,25 +16,27 @@ export const Content = styled.div`
|
|||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
export const SeriesGrid = styled.div`
|
export const SeriesGrid = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-column-gap: ${spacing[4]}px;
|
grid-column-gap: ${spacing[5]}px;
|
||||||
grid-row-gap: ${spacing[6]}px;
|
grid-row-gap: ${spacing[6]}px;
|
||||||
margin-bottom: 5em;
|
margin-bottom: 5em;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
@media screen and (min-width: ${screenSizes.sm}px) {
|
@media screen and (min-width: ${screenSizes.sm}px) {
|
||||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
grid-template-columns: repeat(1, minmax(380px, 1fr));
|
||||||
}
|
}
|
||||||
@media screen and (min-width: ${screenSizes.md}px) {
|
@media screen and (min-width: ${screenSizes.md}px) {
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(380px, 1fr));
|
||||||
}
|
}
|
||||||
@media screen and (min-width: ${screenSizes.lg}px) {
|
@media screen and (min-width: ${screenSizes.lg}px) {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(380px, 1fr));
|
||||||
}
|
}
|
||||||
@media screen and (min-width: ${screenSizes.xl}px) {
|
@media screen and (min-width: ${screenSizes.xl}px) {
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(380px, 1fr));
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -106,7 +106,6 @@ const SeriesPage = ({ data }) => {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
) : null}
|
) : null}
|
||||||
{credits ? <InfoContent>
|
{credits ? <InfoContent>
|
||||||
<Title>Credits</Title>
|
|
||||||
<Markdown theme={theme}>{credits}</Markdown>
|
<Markdown theme={theme}>{credits}</Markdown>
|
||||||
</InfoContent> : null}
|
</InfoContent> : null}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -26,7 +26,7 @@ export const useTheme = create(set => ({
|
|||||||
|
|
||||||
export const useUiStore = create((set, get) => ({
|
export const useUiStore = create((set, get) => ({
|
||||||
mobileMenuOpen: false,
|
mobileMenuOpen: false,
|
||||||
streamPreviewMinimized: true,
|
streamPreviewMinimized: false,
|
||||||
streamActive: false,
|
streamActive: false,
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
BIN
static/meta.png
BIN
static/meta.png
Binary file not shown.
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 232 KiB |
Loading…
Reference in New Issue
Block a user