Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/actions/__test__/program.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,34 @@ describe('Program actions', () => {
mock.restore();
});

test('fetch featured programs', async () => {
const mock = new MockAdapter(axios);
const programs = [{
id: 33,
name: 'Unnamed_Design_3',
content: '<xml><variables></variables></xml>',
admin_tags: ['featured'],
}];

mock.onGet('/api/v1/block-diagrams/', {
params: {
admin_tags: ['featured'],
},
}).reply(200, programs);

const action = fetchPrograms({
params: {
admin_tags: ['featured'],
},
});
const { type } = action;
const payload = await action.payload;

expect(type).toEqual('FETCH_FEATURED_PROGRAMS');
expect(payload).toEqual(programs);
mock.restore();
});

test('remove program', async () => {
const mock = new MockAdapter(axios);

Expand Down
6 changes: 6 additions & 0 deletions src/actions/program.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export const FETCH_USER_PROGRAMS = 'FETCH_USER_PROGRAMS';
export const FETCH_USER_PROGRAMS_PENDING = `${FETCH_USER_PROGRAMS}_PENDING`;
export const FETCH_USER_PROGRAMS_FULFILLED = `${FETCH_USER_PROGRAMS}_FULFILLED`;
export const FETCH_USER_PROGRAMS_REJECTED = `${FETCH_USER_PROGRAMS}_REJECTED`;
export const FETCH_FEATURED_PROGRAMS = 'FETCH_FEATURED_PROGRAMS';
export const FETCH_FEATURED_PROGRAMS_PENDING = `${FETCH_FEATURED_PROGRAMS}_PENDING`;
export const FETCH_FEATURED_PROGRAMS_FULFILLED = `${FETCH_FEATURED_PROGRAMS}_FULFILLED`;
export const FETCH_FEATURED_PROGRAMS_REJECTED = `${FETCH_FEATURED_PROGRAMS}_REJECTED`;
export const REMOVE_PROGRAM = 'REMOVE_PROGRAM';
export const REMOVE_PROGRAM_PENDING = `${REMOVE_PROGRAM}_PENDING`;
export const REMOVE_PROGRAM_FULFILLED = `${REMOVE_PROGRAM}_FULFILLED`;
Expand All @@ -22,6 +26,8 @@ export const fetchPrograms = (xhrOptions) => {

if (xhrOptions && xhrOptions.params && xhrOptions.params.user) {
type = FETCH_USER_PROGRAMS;
} else if (xhrOptions && xhrOptions.params && xhrOptions.params.admin_tags) {
type = FETCH_FEATURED_PROGRAMS;
}

return ({
Expand Down
24 changes: 15 additions & 9 deletions src/components/ProgramCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ProgramCollection extends Component {
}

update = () => {
const { onUpdate, owned } = this.props;
const { onUpdate } = this.props;
const {
page,
ordering,
Expand All @@ -45,7 +45,7 @@ class ProgramCollection extends Component {
params.search = searchQuery;
}

onUpdate(params, owned);
onUpdate(params);
}

toggleOrdering = (name) => {
Expand Down Expand Up @@ -81,11 +81,11 @@ class ProgramCollection extends Component {

render() {
const {
user,
label,
onProgramClick,
onRemoveClick,
programs,
owned,
intl,
tag,
} = this.props;
Expand Down Expand Up @@ -182,7 +182,7 @@ class ProgramCollection extends Component {
</Card.Header>
<Card.Meta>
{
owned ? (
user.username === program.user.username ? (
<FormattedMessage
id="app.program_collection.mine"
description="Label to indicate program owned by user"
Expand All @@ -193,9 +193,14 @@ class ProgramCollection extends Component {
</Card.Meta>
</Card.Content>
<Card.Content extra>
<Button primary id={program.id} data-owned={owned} onClick={onProgramClick}>
<Button
primary
id={program.id}
data-owned={user.username === program.user.username}
onClick={onProgramClick}
>
{
owned ? (
user.username === program.user.username ? (
<FormattedMessage
id="app.program_collection.work"
description="Button label to keep working on program"
Expand All @@ -211,7 +216,7 @@ class ProgramCollection extends Component {
}
</Button>
{
owned ? (
user.username === program.user.username ? (
<Button
negative
id={program.id}
Expand Down Expand Up @@ -251,13 +256,15 @@ class ProgramCollection extends Component {
}

ProgramCollection.defaultProps = {
owned: false,
tag: {
tags: [],
},
};

ProgramCollection.propTypes = {
user: PropTypes.shape({
username: PropTypes.string.isRequired,
}).isRequired,
programs: PropTypes.shape({
next: PropTypes.string,
previous: PropTypes.string,
Expand All @@ -278,7 +285,6 @@ ProgramCollection.propTypes = {
})),
}),
label: PropTypes.string.isRequired,
owned: PropTypes.bool,
onProgramClick: PropTypes.func.isRequired,
onRemoveClick: PropTypes.func.isRequired,
onUpdate: PropTypes.func.isRequired,
Expand Down
83 changes: 66 additions & 17 deletions src/components/ProgramList.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class ProgramList extends Component {
user: user.user_id,
}).then(() => fetchPrograms({
user__not: user.user_id,
})).then(() => fetchPrograms({
admin_tags: 'featured',
})).then(() => fetchTags());
}

Expand All @@ -67,6 +69,9 @@ class ProgramList extends Component {
}))
.then(() => fetchPrograms({
user__not: user.user_id,
}))
.then(() => fetchPrograms({
admin_tags: 'featured',
}));
}

Expand All @@ -87,32 +92,40 @@ class ProgramList extends Component {
});
}

fetch = (params, owned) => {
fetchUserPrograms = (params) => {
const { fetchPrograms, user } = this.props;
fetchPrograms({
user: user.user_id,
...params,
});
}

if (owned) {
fetchPrograms({
user: user.user_id,
...params,
});
} else {
fetchPrograms({
user__not: user.user_id,
...params,
});
}
fetchFeaturedPrograms = (params) => {
const { fetchPrograms } = this.props;
fetchPrograms({
admin_tags: 'featured',
...params,
});
}

fetchOtherPrograms = (params) => {
const { fetchPrograms, user } = this.props;
fetchPrograms({
user__not: user.user_id,
...params,
});
}

programSegment = (programs, tag, label, owned) => (
programSegment = (programs, user, tag, label, onUpdate) => (
<Segment raised style={{ margin: '10px 10% 10px 10%' }}>
<ProgramCollection
programs={programs}
user={user}
tag={tag}
label={label}
owned={owned}
onProgramClick={this.loadProgram}
onRemoveClick={this.showConfirm}
onUpdate={this.fetch}
onUpdate={onUpdate}
/>
</Segment>
)
Expand All @@ -121,8 +134,10 @@ class ProgramList extends Component {
const {
intl,
programs,
user,
tag,
userPrograms,
featuredPrograms,
} = this.props;
const {
confirmOpen,
Expand All @@ -136,6 +151,12 @@ class ProgramList extends Component {
defaultMessage: 'My Programs',
});

const featuredProgramsHeader = intl.formatMessage({
id: 'app.program_list.featured_programs',
description: 'Header for all featured programs',
defaultMessage: 'Featured Programs',
});

const otherProgramsHeader = intl.formatMessage({
id: 'app.program_list.other_programs',
description: 'Header for finding other user\'s programs',
Expand Down Expand Up @@ -189,12 +210,19 @@ class ProgramList extends Component {
{
userPrograms === null
? (<Loader active />)
: this.programSegment(userPrograms, tag, myProgramsHeader, true)
: this.programSegment(userPrograms, user, tag,
myProgramsHeader, this.fetchUserPrograms)
}
{
featuredPrograms === null
? (<Loader active />)
: this.programSegment(featuredPrograms, user, tag,
featuredProgramsHeader, this.fetchFeaturedPrograms)
}
{
programs === null
? (<Loader active />)
: this.programSegment(programs, tag, otherProgramsHeader, false)
: this.programSegment(programs, user, tag, otherProgramsHeader, this.fetchOtherPrograms)
}
<Confirm
header={dialogHeader}
Expand Down Expand Up @@ -223,6 +251,12 @@ ProgramList.defaultProps = {
total_pages: 1,
results: [],
},
featuredPrograms: {
next: null,
previous: null,
total_pages: 1,
results: [],
},
tag: {
tags: [],
},
Expand All @@ -237,6 +271,7 @@ ProgramList.propTypes = {
clearProgram: PropTypes.func.isRequired,
user: PropTypes.shape({
user_id: PropTypes.number.isRequired,
username: PropTypes.string.isRequired,
}).isRequired,
programs: PropTypes.shape({
next: PropTypes.string,
Expand Down Expand Up @@ -266,6 +301,20 @@ ProgramList.propTypes = {
}),
),
}),
featuredPrograms: PropTypes.shape({
next: PropTypes.string,
previous: PropTypes.string,
total_pages: PropTypes.number,
results: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
user: PropTypes.shape({
username: PropTypes.string.isRequired,
}).isRequired,
}),
),
}),
tag: PropTypes.shape({
tags: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
Expand Down
Loading