protected $hidden = [
'created_at',
- 'ext_id',
'updated_at',
];
import CrewMember from './CrewMember';
import Icon from '../common/Icon';
import { compareCrew } from '../../helpers/Crew';
+import {
+ getSGLanguages,
+ getSGSignupLink,
+ hasPassed,
+ hasSGRestream,
+} from '../../helpers/Episode';
import { canApplyForEpisode } from '../../helpers/permissions';
import { withUser } from '../../helpers/UserContext';
episode.crew.filter(c => c.role === 'setup').sort(compareCrew)
, [episode]);
+ const sgLanguages = React.useMemo(() =>
+ getSGLanguages(episode)
+ , [episode]);
+
+ const showCommentators = React.useMemo(() =>
+ commentators.length || (!hasPassed(episode) && (
+ canApplyForEpisode(user, episode, 'commentary') ||
+ hasSGRestream(episode)
+ ))
+ , [commentators, episode, user]);
+
+ const showTracker = React.useMemo(() =>
+ trackers.length || (!hasPassed(episode) && (
+ canApplyForEpisode(user, episode, 'tracking') ||
+ hasSGRestream(episode)
+ ))
+ , [episode, trackers, user]);
+
return <Row className="episode-crew">
- {commentators.length || canApplyForEpisode(user, episode, 'commentary') ?
+ {showCommentators ?
<Col md>
<div className="fs-5">
<Icon.MICROPHONE className="ms-3 me-2" title="" />
</Button>
</div>
: null}
+ {hasSGRestream(episode) ?
+ <div className="button-bar m-2">
+ {sgLanguages.map(lang =>
+ <Button
+ href={getSGSignupLink(episode, lang, 'commentator')}
+ key={lang}
+ target="_blank"
+ variant="outline-secondary"
+ >
+ {`${t('episodes.sgSignUp')} ${lang.toUpperCase()}`}
+ </Button>
+ )}
+ </div>
+ : null}
</Col>
: null}
- {trackers.length || canApplyForEpisode(user, episode, 'tracking') ?
+ {showTracker ?
<Col md>
<div className="fs-5">
<Icon.MOUSE className="ms-3 me-2" title="" />
</Button>
</div>
: null}
+ {hasSGRestream(episode) ?
+ <div className="button-bar m-2">
+ {sgLanguages.map(lang =>
+ <Button
+ href={getSGSignupLink(episode, lang, 'tracker')}
+ key={lang}
+ target="_blank"
+ variant="outline-secondary"
+ >
+ {`${t('episodes.sgSignUp')} ${lang.toUpperCase()}`}
+ </Button>
+ )}
+ </div>
+ : null}
</Col>
: null}
{techies.length ?
-import moment from 'moment';
import PropTypes from 'prop-types';
import React from 'react';
import { Button } from 'react-bootstrap';
import MultiLink from './MultiLink';
import Players from './Players';
import Icon from '../common/Icon';
+import { hasPassed, hasSGRestream, isActive } from '../../helpers/Episode';
import { canApplyForEpisode, canRestreamEpisode } from '../../helpers/permissions';
import { withUser } from '../../helpers/UserContext';
-const isActive = episode => {
- if (!episode.start) return false;
- const now = moment();
- const start = moment(episode.start).subtract(10, 'minutes');
- const end = moment(episode.start).add(episode.estimate, 'seconds');
- return start.isBefore(now) && end.isAfter(now);
-};
-
const Item = ({ episode, onAddRestream, onApply, onEditRestream, user }) => {
const { t } = useTranslation();
{hasPlayers ?
<Players players={episode.players} />
: null}
- {(episode.crew && episode.crew.length)
+ {(episode.crew && episode.crew.length) || (!hasPassed(episode) && (
+ hasSGRestream(episode)
|| canApplyForEpisode(user, episode, 'commentary')
- || canApplyForEpisode(user, episode, 'tracking') ?
+ || canApplyForEpisode(user, episode, 'tracking')
+ )) ?
<div className="mb-3">
<Crew episode={episode} onApply={onApply} />
</div>
: null}
{episode.event ?
<div className="episode-event mt-auto">
- <Link className="event-link" to={`/events/${episode.event.name}`}>
- {episode.event.title}
- </Link>
+ {episode.event.description_id ?
+ <Link className="event-link" to={`/events/${episode.event.name}`}>
+ {episode.event.title}
+ </Link>
+ :
+ episode.event.title
+ }
</div>
: null}
</div>
})),
event: PropTypes.shape({
corner: PropTypes.string,
+ description_id: PropTypes.number,
name: PropTypes.string,
title: PropTypes.string,
}),
+import moment from 'moment';
+
export const acceptsComms = episode => {
if (!episode || !episode.channels) return false;
return !!episode.channels.find(c => c.pivot && c.pivot.accept_comms);
c.pivot && (c.pivot.accept_comms || c.pivot.accept_tracker));
};
+export const getSGLanguages = episode => {
+ if (!episode || !episode.channels) return [];
+ const sgChannels = episode.channels.filter(
+ c => c.stream_link && c.stream_link.startsWith('https://twitch.tv/speedgaming'),
+ );
+ const langs = [];
+ sgChannels.forEach(channel => {
+ if (!channel.languages) return;
+ channel.languages.forEach(lang => {
+ if (!langs.includes(lang)) {
+ langs.push(lang);
+ }
+ });
+ });
+ return langs;
+};
+
+export const getSGSignupLink = (episode, lang, role) =>
+ `https://speedgaming.org/${lang}/${role}/signup/${episode.ext_id.substr(3)}/`;
+
+export const hasPassed = episode => {
+ if (!episode || !episode.start) return false;
+ const now = moment();
+ const end = moment(episode.start).add(episode.estimate, 'seconds');
+ return end.isBefore(now);
+};
+
+export const hasSGRestream = episode => {
+ if (!episode || !episode.channels) return false;
+ return !!episode.channels.find(
+ c => c.stream_link && c.stream_link.startsWith('https://twitch.tv/speedgaming'),
+ );
+};
+
+export const isActive = episode => {
+ if (!episode || !episode.start) return false;
+ const now = moment();
+ const start = moment(episode.start).subtract(10, 'minutes');
+ const end = moment(episode.start).add(episode.estimate, 'seconds');
+ return start.isBefore(now) && end.isAfter(now);
+};
+
export const isEventSelected = (filter, event) => {
return (filter.event || []).includes(event.id);
};
title: 'Restream',
},
setup: 'Setup',
+ sgSignUp: 'SG Anmeldung',
startTime: '{{ date, LL LT }} Uhr',
tracking: 'Tracking',
},
title: 'Restream',
},
setup: 'Setup',
+ sgSignUp: 'SG Signup',
startTime: '{{ date, LL LT }}',
tracking: 'Tracking',
},