Skip to content

Commit

Permalink
Merge e8b34e1 into 71c7f99
Browse files Browse the repository at this point in the history
  • Loading branch information
gupta-utkarsh committed Aug 26, 2017
2 parents 71c7f99 + e8b34e1 commit 79b6b8b
Show file tree
Hide file tree
Showing 20 changed files with 357 additions and 34 deletions.
4 changes: 2 additions & 2 deletions apps/demos/views.py
Expand Up @@ -12,7 +12,7 @@
@permission_classes((permissions.AllowAny,))
def get_demos(request):
"""
Get a list of team members
Get a list of demos
"""
demos = Demo.objects.filter(is_disabled=False).order_by('title')
serializer = DemoSerializer(demos, many=True, context={'request': request})
Expand All @@ -25,7 +25,7 @@ def get_demos(request):
@permission_classes((permissions.AllowAny,))
def get_projects(request):
"""
Get a list of team members
Get a list of projects
"""
projects = Project.objects.filter(is_visible=True).order_by('title')
serializer = ProjectSerializer(projects, many=True, context={'request': request})
Expand Down
9 changes: 9 additions & 0 deletions apps/logs/urls.py
@@ -0,0 +1,9 @@
from django.conf.urls import url

from .import views


urlpatterns = [
url(r'^(?P<demo_permalink>[A-Za-z]+)/add/$', views.post_log, name='post_log'),
url(r'^(?P<log_id>[0-9]+)/output/$', views.post_output, name='post_output'),
]
102 changes: 102 additions & 0 deletions apps/logs/views.py
@@ -0,0 +1,102 @@
import logging
from rest_framework import permissions, status
from rest_framework.decorators import (api_view, permission_classes, throttle_classes,)
from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle
from base64 import b64decode
from django.core.files.base import ContentFile

from demos.models import Demo
from .models import DemoLog, LogImage, LogText


@throttle_classes([AnonRateThrottle, ])
@api_view(['POST'])
@permission_classes((permissions.AllowAny,))
def post_log(request, demo_permalink):
"""
Create and save a log
"""
demo = Demo.objects.get(permalink=demo_permalink)
if not demo:
error_message = {'error': 'Demo not found!'}
return Response(error_message, status=status.HTTP_404_NOT_FOUND)

try:
demo_log = DemoLog.objects.create(
demo=demo,
log_type='Submission'
)
except Exception:
error_message = {'error': 'Demo log could not be created'}
return Response(error_message, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

i = 0
try:
while True:
textdata = request.data['input-text-{}'.format(i)]
LogText.objects.create(
demo_log=demo_log,
text=textdata,
text_type='Input'
)
i += 1
except Exception:
logging.exception('Key not found while saving input')
pass

imagedata = []
i = 0
try:
while True:
imagedata = request.FILES['input-image-{}'.format(i)]
LogImage.objects.create(
demo_log=demo_log,
image=imagedata,
image_type='Input'
)
i += 1
except Exception:
logging.exception('Key not found while saving output')
pass

success_message = {'success': {'id': demo_log.id}}
return Response(success_message, status=status.HTTP_200_OK)


@throttle_classes([AnonRateThrottle, ])
@api_view(['POST'])
@permission_classes((permissions.AllowAny,))
def post_output(request, log_id):
"""
Get a list of projects
"""
demo_log = DemoLog.objects.get(id=log_id)
if not demo_log:
error_message = {'error': 'Demo log not found!'}
return Response(error_message, status=status.HTTP_404_NOT_FOUND)

count_image_inputs = demo_log.demo.image_inputs
count_text_inputs = demo_log.demo.text_inputs

if count_image_inputs > 0 and count_text_inputs == 0:
for image in request.data:
image = str(image).split(",")[1]
missing_padding = len(image) % 4
if missing_padding != 0:
image += b'=' * (4 - missing_padding)
image_data = b64decode(image)
LogImage.objects.create(
demo_log=demo_log,
image=ContentFile(image_data, 'whatup.png'),
image_type='Output'
)
elif count_text_inputs > 0 and count_image_inputs == 0:
for text in request.data:
LogText.objects.create(
demo_log=demo_log,
text=text,
text_type='Output'
)
success_message = {'success': 'OK'}
return Response(success_message, status=status.HTTP_200_OK)
3 changes: 2 additions & 1 deletion cloudcv/urls.py
Expand Up @@ -21,5 +21,6 @@
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/web/', include('web.urls', namespace='web')),
url(r'^api/demos/', include('demos.urls', namespace='demos'))
url(r'^api/demos/', include('demos.urls', namespace='demos')),
url(r'^api/logs/', include('logs.urls', namespace='logs'))
] + static(MEDIA_URL, document_root=MEDIA_ROOT)
4 changes: 3 additions & 1 deletion frontend/package.json
Expand Up @@ -45,7 +45,8 @@
"redux-thunk": "^2.1.0",
"socket.io": "^2.0.1",
"socket.io-client": "^2.0.1",
"superagent": "^3.0.0"
"superagent": "^3.0.0",
"to-string-loader": "^1.1.5"
},
"devDependencies": {
"autoprefixer": "^7.1.1",
Expand All @@ -60,6 +61,7 @@
"babel-preset-react": "^6.16.0",
"babel-preset-react-hmre": "^1.1.1",
"babel-register": "^6.16.3",
"base64-font-loader": "^0.0.4",
"colors": "^1.1.2",
"compression": "^1.6.2",
"cross-env": "4.0.0",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/App.js
Expand Up @@ -16,10 +16,10 @@ const App = props => {
<Route component={AnalyticsComponent} />
<Switch>
<Route exact path="/" component={HomePageComponent} />
<Route path="/news" component={HomePageComponent} />
<Route path="/team" component={TeamPageComponent} />
<Route path="/projects" component={ProjectPageComponent} />
<Route path="/contact-us" component={HomePageComponent} />
<Route path="/contribute" component={HomePageComponent} />
<Route component={PageNotFoundHandler} />
</Switch>
</main>
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/components/common/Card.js
Expand Up @@ -10,7 +10,11 @@ const Card = props => {
);
};

const themeClassOptions = ["cv-card-light", "cv-card-dark"];
const themeClassOptions = [
"cv-card-light",
"cv-card-dark",
"cv-card-deep-light"
];

Card.defaultProps = {
children: null,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/home/HomeBody.js
Expand Up @@ -21,7 +21,7 @@ const HomeBody = props => {
<HomeNews />
<HomeShowcase />
<HomeSponsors />
<div className="cv-home-github cv-container">
<div className="cv-home-github cv-container" id="contribute">
<h1 className="cv-home-showcase-heading">{GITHUB_DESC}</h1>
<br />
<p>{GITHUB_STRING}</p>
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/components/navbar/index.js
Expand Up @@ -53,13 +53,21 @@ class Navbar extends Component {
let listItems = [
"",
"Projects",
"News",
"GSoC",
"Team",
"Contribute",
"Contact Us"
];
listItems = listItems.map((path, index) => {
if (path === "GSoC") {
return (
<NavbarItem active={false} key={path}>
<Link to="http://gsoc.cloudcv.org" target="_blank">
{path}
</Link>
</NavbarItem>
);
}
let active = path.toLowerCase() === firstPath;
let formattedPath = path.toLowerCase().replace(/ /g, "-");
return (
Expand Down
67 changes: 67 additions & 0 deletions frontend/src/components/projects/DemoContainer.js
@@ -1,5 +1,8 @@
import React from "react";
import { PropTypes } from "prop-types";
import styles from "../../styles/demo.scss";
import axios from "axios";
const AJAX_ROOT = process.env.AJAX_ROOT;

class DemoContainer extends React.Component {
constructor(props) {
Expand All @@ -8,6 +11,70 @@ class DemoContainer extends React.Component {
demo: this.props.demo,
height: "auto"
};
this.receiveMessage = this.receiveMessage.bind(this);
this.sendStyleSheet = this.sendStyleSheet.bind(this);
this.saveInput = this.saveInput.bind(this);
this.saveOutput = this.saveOutput.bind(this);
this.log = -1;
window.addEventListener("message", this.receiveMessage, false);
}

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

saveInput(data) {
let formData = new FormData();
Object.entries(data).forEach(([key, value]) => {
if (value instanceof Blob) formData.set(key, value, key);
else formData.set(key, value);
});
axios({
method: "post",
url: `${process.env.AJAX_ROOT}/api/logs/${this.state.demo.permalink}/add/`,
data: formData
})
.then(response => {
if (response.status === 200) this.log = response.data.success.id;
})
.catch(error => {});
}

saveOutput(formData) {
if (this.log !== -1)
axios({
method: "post",
url: `${process.env.AJAX_ROOT}/api/logs/${this.log}/output/`,
data: formData
})
.then(response => {
if (response.status === 200) this.log = -1;
})
.catch(error => {});
}

sendStyleSheet() {
let iframeWindow = document.getElementsByTagName("iframe")[0].contentWindow;
let stylesheet = {
action: "STYLESHEET_SEND",
styles: styles.toString()
};
iframeWindow.postMessage(stylesheet, "*");
}

receiveMessage(message) {
switch (message.data.action) {
case "DEMO_ONLOAD":
this.sendStyleSheet();
break;
case "INPUT_SUBMITTED":
this.saveInput(message.data.payload);
break;
case "OUTPUT_SUBMITTED":
this.saveOutput(message.data.payload);
break;
}
}

render() {
Expand Down
11 changes: 7 additions & 4 deletions frontend/src/components/projects/index.js
Expand Up @@ -19,6 +19,9 @@ class Projects extends React.Component {
showQueue: this.props.showQueue
};
this.fetchDemos = this.fetchDemos.bind(this);
}

componentDidMount() {
this.fetchDemos();
}

Expand Down Expand Up @@ -47,9 +50,9 @@ class Projects extends React.Component {
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;
this.props.location.pathname === link ||
(this.props.location.pathname === "/projects" && index === 0);
if (active) activeDemo = demo;
return {
name: demo.tag_line,
link,
Expand All @@ -76,7 +79,7 @@ class Projects extends React.Component {
}

Projects.propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
sidebarActions: PropTypes.object.isRequired,
showQueue: PropTypes.bool.isRequired
};
Expand Down

0 comments on commit 79b6b8b

Please sign in to comment.