Skip to content

Commit

Permalink
Finish projects page
Browse files Browse the repository at this point in the history
  • Loading branch information
gupta-utkarsh committed Aug 2, 2017
1 parent 1ecd4b5 commit c215235
Show file tree
Hide file tree
Showing 18 changed files with 396 additions and 21 deletions.
32 changes: 32 additions & 0 deletions apps/demos/migrations/0002_auto_20170801_0515.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.1 on 2017-08-01 05:15
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('demos', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='demo',
name='demo_base_url',
field=models.URLField(default='permalink', max_length=100),
preserve_default=False,
),
migrations.AddField(
model_name='demo',
name='permalink',
field=models.CharField(default='permalink', max_length=100),
preserve_default=False,
),
migrations.AlterField(
model_name='demo',
name='demo_url',
field=models.URLField(),
),
]
4 changes: 3 additions & 1 deletion apps/demos/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
class Demo(models.Model):
""""Models representing details of Demo."""
title = models.CharField(max_length=40)
demo_url = models.URLField(max_length=100)
demo_url = models.URLField(max_length=200)
demo_base_url = models.URLField(max_length=100)
permalink = models.CharField(max_length=100)
tag_line = models.CharField(max_length=140, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
source_code_url = models.URLField(max_length=100, null=True, blank=True)
Expand Down
5 changes: 3 additions & 2 deletions apps/demos/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ class DemoSerializer(serializers.ModelSerializer):

class Meta:
model = Demo
fields = ('title', 'demo_url', 'tag_line', 'description', 'source_code_url', 'paper_description', 'paper_url',
'sample', 'text_inputs', 'image_inputs', 'text_outputs', 'image_outputs')
fields = ('title', 'demo_url', 'permalink', 'demo_base_url', 'tag_line', 'description', 'source_code_url',
'paper_description', 'paper_url', 'sample', 'text_inputs', 'image_inputs', 'text_outputs',
'image_outputs')
20 changes: 20 additions & 0 deletions apps/web/migrations/0003_auto_20170801_0507.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.1 on 2017-08-01 05:07
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('web', '0002_team_year'),
]

operations = [
migrations.AlterField(
model_name='team',
name='team_type',
field=models.CharField(choices=[('Team', 'Team'), ('GSoC Students, Mentors and Interns', 'GSoC Students, Mentors and Interns'), ('Contributors', 'Contributors')], max_length=50),
),
]
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"prop-types": "^15.5.8",
"raven-js": "^3.16.0",
"react": "^15.4.2",
"react-burger-menu": "^2.1.4",
"react-dom": "^15.3.2",
"react-redux": "^5.0.3",
"react-router-dom": "^4.1.1",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/actions/actionTypes.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@

export const TOGGLE_SHOW_QUEUE = "TOGGLE_SHOW_QUEUE";
14 changes: 14 additions & 0 deletions frontend/src/actions/sidebarActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as types from "./actionTypes";

function toggleShowQueueSuccess(value) {
return { type: types.TOGGLE_SHOW_QUEUE, value };
}

export function toggleShowQueue(value) {
return function(dispatch) {
return new Promise((resolve, reject) => {
dispatch(toggleShowQueueSuccess(value));
resolve("dispatch showQueue value change call");
});
};
}
45 changes: 42 additions & 3 deletions frontend/src/components/navbar/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, { Component } from "react";
import { PropTypes } from "prop-types";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import * as sidebarActions from "../../actions/sidebarActions";
import { Link, withRouter } from "react-router-dom";
import NavbarItem from "./NavbarItem";

Expand All @@ -12,13 +15,18 @@ class Navbar extends Component {
};
this.handleClick = this.handleClick.bind(this);
this.handleScroll = this.handleScroll.bind(this);
this.showSidebarOnProjectsPage = this.showSidebarOnProjectsPage.bind(this);
window.addEventListener("scroll", this.handleScroll);
}

componentWillUnmount() {
window.removeEventListener("scroll");
}

showSidebarOnProjectsPage() {
this.props.sidebarActions.toggleShowQueue(!this.props.showQueue);
}

handleScroll(event) {
let isOnTop = document.body.scrollTop === 0;
this.setState({ isOnTop });
Expand All @@ -29,9 +37,17 @@ class Navbar extends Component {
}

render() {
let x = this.props.location.pathname.indexOf("/", 1);
let firstPath;
if (x !== -1) {
firstPath = this.props.location.pathname.substr(1, x - 1);
} else {
firstPath = this.props.location.pathname.substr(1);
}
let projectActive = firstPath === "projects";
let listItems = ["", "Projects", "News", "GSoC", "Team", "Contribute"];
listItems = listItems.map((path, index) => {
let active = `/${path.toLowerCase()}` === this.props.location.pathname;
let active = path.toLowerCase() === firstPath;
return (
<NavbarItem active={active} key={path}>
<Link to={`\/${path.toLowerCase()}`}>
Expand All @@ -41,6 +57,7 @@ class Navbar extends Component {
);
});
let listHiddenClass = this.state.isOpen ? "" : "hidden-small";
let sidebarIconClass = "cv-navbar-list-icon";
let listIconClass = this.state.isOpen
? "cv-navbar-close-icon"
: "cv-navbar-list-icon";
Expand All @@ -53,6 +70,11 @@ class Navbar extends Component {
</ul>
</div>
<div className="cv-mobile-topbar">
{projectActive &&
<div
className={`cv-icon ${sidebarIconClass}`}
onClick={this.showSidebarOnProjectsPage}
/>}
<div className="cv-navbar-brand">
<img
className="cv-navbar-brand-image"
Expand All @@ -74,7 +96,24 @@ class Navbar extends Component {
Navbar.propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
history: PropTypes.object.isRequired,
sidebarActions: PropTypes.object.isRequired,
showQueue: PropTypes.bool.isRequired
};

export default withRouter(Navbar);
function mapStateToProps(state, ownProps) {
return {
showQueue: state.sidebar.showQueue,
match: ownProps.match,
location: ownProps.location,
history: ownProps.history
};
}

function mapDispatchToProps(dispatch) {
return {
sidebarActions: bindActionCreators(sidebarActions, dispatch)
};
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Navbar));
30 changes: 30 additions & 0 deletions frontend/src/components/projects/DemoContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import { PropTypes } from "prop-types";

class DemoContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
demo: this.props.demo,
height: "auto"
};
}

render() {
return (
<main className="cv-project-demo-container">
<iframe
className="cv-project-demo-iframe"
src={this.state.demo.demo_url}
height={this.state.height}
/>
</main>
);
}
}

DemoContainer.propTypes = {
demo: PropTypes.object.isRequired
};

export default DemoContainer;
19 changes: 18 additions & 1 deletion frontend/src/components/projects/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ProjectSidebar extends React.Component {
}

render() {
const DEMOS = this.props.demos;
const PROJECTS = [
{
link: "https://evalai.cloudcv.org/",
Expand All @@ -27,7 +28,19 @@ class ProjectSidebar extends React.Component {
<aside className="cv-project-sidebar">
<section className="cv-project-sections">
<h6 className="cv-project-list-heading">Demos</h6>
<ul className="cv-project-list" />
<ul className="cv-project-list">
{DEMOS.map((project, index) => {
let activeClass = project.active ? "active" : "";
return (
<li
key={index}
className={`cv-project-list-item ${activeClass}`}
>
<Link to={project.link}>{project.name}</Link>
</li>
);
})}
</ul>
</section>
<section className="cv-project-sections">
<h6 className="cv-project-list-heading">Projects</h6>
Expand All @@ -46,4 +59,8 @@ class ProjectSidebar extends React.Component {
}
}

ProjectSidebar.propTypes = {
demos: PropTypes.array
};

export default ProjectSidebar;
73 changes: 65 additions & 8 deletions frontend/src/components/projects/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import React from "react";
import { PropTypes } from "prop-types";
import axios from "axios";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import { slide as Menu } from "react-burger-menu";
import Preloader from "../common/Preloader";
import Sidebar from "./Sidebar";
import DemoContainer from "./DemoContainer";
import * as sidebarActions from "../../actions/sidebarActions";
const AJAX_ROOT = process.env.AJAX_ROOT;

class Projects extends React.Component {
constructor(props) {
super(props);
this.state = {
isFetching: true,
demos: []
demos: [],
showQueue: this.props.showQueue
};
this.fetchDemos = this.fetchDemos.bind(this);
this.fetchDemos();
}

componentWillReceiveProps(nextProps) {
if (this.state.showQueue !== nextProps.showQueue) {
this.setState({ showQueue: nextProps.showQueue });
}
}

fetchDemos() {
axios
.get(`http://${process.env.AJAX_ROOT}/api/demos/all/`)
Expand All @@ -25,15 +37,60 @@ class Projects extends React.Component {
.catch(error => {});
}

isMenuOpen(state) {
this.props.sidebarActions.toggleShowQueue(state.isOpen);
}

render() {
if (this.state.isFetching) return <Preloader />;
else
return (
<section className="cv-project-section">
<Sidebar />
</section>
);
let activeDemo = null;
let sidebarLinks = this.state.demos.map((demo, index) => {
let link = `/projects/${demo.permalink}`;
let active =
this.props.match.path === link ||
(this.props.match.path === "/projects" && index === 0);
activeDemo = demo;
return {
name: demo.tag_line,
link,
active
};
});
return (
<section className="cv-project-section">
<Menu
className="cv-mobile-sidebar"
isOpen={this.state.showQueue}
onStateChange={this.isMenuOpen.bind(this)}
customBurgerIcon={false}
customCrossIcon={false}
width={"120px"}
>
<Sidebar demos={sidebarLinks} />
</Menu>
<Sidebar demos={sidebarLinks} />
{activeDemo && <DemoContainer demo={activeDemo} />}
</section>
);
}
}

export default Projects;
Projects.propTypes = {
match: PropTypes.object.isRequired,
sidebarActions: PropTypes.object.isRequired,
showQueue: PropTypes.bool.isRequired
};

function mapStateToProps(state, ownProps) {
return {
showQueue: state.sidebar.showQueue
};
}

function mapDispatchToProps(dispatch) {
return {
sidebarActions: bindActionCreators(sidebarActions, dispatch)
};
}

export default connect(mapStateToProps, mapDispatchToProps)(Projects);
3 changes: 2 additions & 1 deletion frontend/src/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { combineReducers } from "redux";

const rootReducer = combineReducers({});
import sidebar from "./sidebarReducer";
const rootReducer = combineReducers({ sidebar });

export default rootReducer;
4 changes: 3 additions & 1 deletion frontend/src/reducers/initialState.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export default {
holder: []
sidebar: {
showQueue: false
}
};
11 changes: 11 additions & 0 deletions frontend/src/reducers/sidebarReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as types from "../actions/actionTypes";
import initialState from "./initialState";

export default function sidebarReducer(state = initialState.sidebar, action) {
switch (action.type) {
case "TOGGLE_SHOW_QUEUE":
return Object.assign({}, state, { showQueue: action.value });
default:
return state;
}
}

0 comments on commit c215235

Please sign in to comment.