Skip to content

Commit

Permalink
Podcast implementation v.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
SmithPeder committed Oct 24, 2018
1 parent da57b81 commit db743b0
Show file tree
Hide file tree
Showing 12 changed files with 1,933 additions and 349 deletions.
52 changes: 14 additions & 38 deletions app/actions/PodcastAction.js
@@ -1,12 +1,9 @@
// @flow

import { Podcast } from './ActionTypes';
import { push } from 'react-router-redux';
import { podcastSchema } from 'app/reducers';
import callAPI from 'app/actions/callAPI';
import { startSubmit, stopSubmit } from 'redux-form';
import type { Thunk } from 'app/types';
import { addToast } from 'app/actions/ToastActions';

export function fetchPodcasts() {
return callAPI({
Expand Down Expand Up @@ -47,42 +44,21 @@ export function deletePodcast(podcastId: number) {
});
}

export function addPodcast({
title,
source,
description
}: {
export function addPodcast(data: {
title: string,
source: string,
description: string
description: string,
authors: Array<number>
}): Thunk<*> {
return dispatch => {
dispatch(startSubmit('createPodcast'));

return dispatch(
callAPI({
types: Podcast.CREATE,
endpoint: '/podcasts/',
method: 'POST',
body: {
title,
source,
description
},
schema: podcastSchema,
meta: {
errorMessage: 'Legg til podcast feilet'
}
})
).then(() => {
dispatch(stopSubmit('createPodcast'));
dispatch(push('/podcasts'));
dispatch(
addToast({
message: 'Podcast sendt inn.',
dismissAfter: 10000
})
);
});
};
return callAPI({
types: Podcast.CREATE,
endpoint: '/podcasts/',
method: 'POST',
body: data,
schema: podcastSchema,
meta: {
errorMessage: 'Legg til podcast feilet',
successMessage: 'Podcast lagt til'
}
});
}
1 change: 1 addition & 0 deletions app/routes/events/components/EventList.js
Expand Up @@ -124,6 +124,7 @@ type EventListProps = {
fetchMore: () => Promise<*>
};

// $FlowFixMe
const EventList = (props: EventListProps) => {
const events = groupEvents(props.events);
const { icalToken, showFetchMore, fetchMore } = props;
Expand Down
12 changes: 9 additions & 3 deletions app/routes/podcasts/PodcastCreateRoute.js
Expand Up @@ -2,18 +2,24 @@ import { compose } from 'redux';
import { connect } from 'react-redux';

import { selectPodcasts } from 'app/reducers/podcasts';
import { fetchPodcasts } from 'app/actions/PodcastAction';
import { fetchPodcasts, addPodcast } from 'app/actions/PodcastAction';
import prepare from 'app/utils/prepare';
import PodcastEditor from './components/PodcastEditor';

const mapStateToProps = (state, props) => {
return {
new: true,
podcasts: selectPodcasts(state),
actionGrant: state.podcasts.actionGrant
actionGrant: state.podcasts.actionGrant,
initialValues: {}
};
};

const mapDispachToProps = {
handleSubmitCallback: addPodcast
};

export default compose(
prepare((props, dispatch) => dispatch(fetchPodcasts())),
connect(mapStateToProps, null)
connect(mapStateToProps, mapDispachToProps)
)(PodcastEditor);
30 changes: 26 additions & 4 deletions app/routes/podcasts/PodcastEditRoute.js
Expand Up @@ -2,22 +2,44 @@ import { compose } from 'redux';
import { connect } from 'react-redux';

import { selectPodcastById } from 'app/reducers/podcasts';
import { fetchPodcasts, deletePodcast } from 'app/actions/PodcastAction';
import {
fetchPodcasts,
deletePodcast,
addPodcast
} from 'app/actions/PodcastAction';
import prepare from 'app/utils/prepare';
import PodcastEditor from './components/PodcastEditor';
import { push } from 'react-router-redux';
import loadingIndicator from 'app/utils/loadingIndicator';

const mapDispachToProps = { deletePodcast, push };
const mapDispachToProps = {
deletePodcast,
push,
handleSubmitCallback: addPodcast
};

const mapStateToProps = (state, props) => {
const id = props.params.podcastId;
const podcast = selectPodcastById(state, id) || {};

return {
...selectPodcastById(state, id),
initialValues: {
...podcast,
authors: (podcast.authors || []).filter(Boolean).map(user => ({
label: user.username,
value: user.id
})),
thanks: (podcast.thanks || []).filter(Boolean).map(user => ({
label: user.username,
value: user.id
}))
},
actionGrant: state.podcasts.actionGrant
};
};

export default compose(
prepare((props, dispatch) => dispatch(fetchPodcasts())),
connect(mapStateToProps, mapDispachToProps)
connect(mapStateToProps, mapDispachToProps),
loadingIndicator(['initialValues.id'])
)(PodcastEditor);
59 changes: 40 additions & 19 deletions app/routes/podcasts/components/Podcast.css
Expand Up @@ -19,11 +19,6 @@
width: 100%;
padding: 0 10px;
border-bottom: 2px solid var(--color-red-3);

@media (--mobile-device) {
flex-direction: column;
align-items: flex-start;
}
}

.title {
Expand All @@ -32,19 +27,43 @@
margin: 0;
}

.player {
display: flex;
flex-direction: column;
padding: 5px;
}

.playerRow {
align-items: center;
margin-top: 5px;
}

.init {
font-weight: bold;
margin-right: 10px;
}

.talking {
display: flex;
align-items: center;

@media (--mobile-device) {
flex-direction: column;
align-items: flex-start;
}
}

.published {
background: var(--color-red-5);
padding: 5px;
color: white;
border-radius: 5px;
}

.names {
padding: 10px;

@media (--mobile-device) {
padding: 2px;
}

&:hover {
font-weight: bold;
}
}

.playButton {
Expand Down Expand Up @@ -75,20 +94,20 @@

.volume::-webkit-slider-thumb {
height: 15px !important;
width: 15px;
overflow: auto;
border-radius: 15px;
width: 15px !important;
overflow: auto !important;
border-radius: 15px !important;
background: var(--color-red-3) !important;
cursor: pointer;
margin-top: -6px;
-webkit-appearance: none;
cursor: pointer !important;
margin-top: -6px !important;
-webkit-appearance: none !important;
}

.progress {
height: 30px !important;
width: 100%;
width: 100% !important;
border-radius: 10px !important;
opacity: 0.5 !important;
opacity: 0.9 !important;
}

.progressInner {
Expand All @@ -101,6 +120,8 @@
padding-right: 10px;
margin-top: -38px;
white-space: nowrap;
pointer-events: none;
z-index: 10;
}

.more {
Expand Down
73 changes: 63 additions & 10 deletions app/routes/podcasts/components/Podcast.js
Expand Up @@ -5,14 +5,17 @@ import styles from './Podcast.css';
import LegoSoundCloudPlayer from './PodcastPlayer.js';
import { Link } from 'react-router';
import Icon from 'app/components/Icon';
import { ProfilePicture } from 'app/components/Image';
import moment from 'moment-timezone';

type Props = {
id: number,
title: string,
source: string,
createdAt: string,
description: string,
authors: Array<Object>
authors: Array<Object>,
thanks: Array<Object>,
actionGrant: Array<String>
};

type State = {
Expand All @@ -33,11 +36,48 @@ class Podcast extends Component<Props, State> {
render() {
const CLIENT_ID = 'E8IqLGTYxHll6SyaM7LKrMzKveWkcrjg';

const { id, source, createdAt, description, authors } = this.props;
const talking = authors.map(author => {
const {
id,
source,
createdAt,
description,
authors,
thanks,
actionGrant
} = this.props;

const authorsSpan = authors.map(user => {
return (
<span key={author.id} className={styles.names}>
<Link to={`/users/${author.username}`}>{author.fullName}</Link>
<span key={user.id} className={styles.names}>
<Link
to={`/users/${user.username}`}
style={{ display: 'flex', alignItems: 'center' }}
>
<ProfilePicture
size={40}
user={user}
style={{ marginRight: '10px' }}
/>
{user.fullName}
</Link>
</span>
);
});

const thanksSpan = thanks.map(user => {
return (
<span key={user.id} className={styles.names}>
<Link
to={`/users/${user.username}`}
style={{ display: 'flex', alignItems: 'center' }}
>
<ProfilePicture
size={40}
user={user}
style={{ marginRight: '10px' }}
/>
{user.fullName}
</Link>
</span>
);
});
Expand All @@ -46,17 +86,30 @@ class Podcast extends Component<Props, State> {
<div className={styles.root}>
<LegoSoundCloudPlayer
id={id}
createdAt={createdAt}
clientId={CLIENT_ID}
resolveUrl={source}
actionGrant={actionGrant}
/>
{this.state.extended && (
<div className={styles.more}>
<p style={{ fontWeight: 'bold' }}>Snakker: {talking}</p>
<p style={{ textAlign: 'justify' }}>{description}</p>
<div className={styles.talking}>
<span className={styles.init}>Snakker</span> {authorsSpan}
</div>
<p>
<span className={styles.init}>Publisert</span>
<span className={styles.published}>
{moment(createdAt).format('Do MMM YY')}
</span>
</p>
<p style={{ textAlign: 'justify' }}>
<span className={styles.init}>Om </span>
{description}
</p>
<div className={styles.talking}>
<span className={styles.init}>Takk til</span> {thanksSpan}
</div>
</div>
)}

<div className={styles.showMore}>
{this.state.extended ? (
<Icon
Expand Down

0 comments on commit db743b0

Please sign in to comment.