Skip to content

Commit

Permalink
course_material admin. Fixes #141. Fixes #153.
Browse files Browse the repository at this point in the history
  • Loading branch information
brunosmartin committed Nov 11, 2013
1 parent 66c90cd commit ebc9baf
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 16 deletions.
7 changes: 6 additions & 1 deletion core/templates/admin/_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ <h1 class="top editable"><span contenteditable="true" ng-model="course.name"></s
<h5><span class="icon-addable icon-plus-sign-alt"></span> Adicionar professores ao curso</h5>
</div>
<div class="col-sm-3 col-lg-3 textright">
<a href="aula.html" class="btn btn-lg btn-info col-lg-12 uppercase disabled">Começar o curso</a>
<!-- COURSE-SECTION-NAV -->
<nav class="course-sections textright">
<a href="{% url 'course_admin' course.slug %}"><span class="has-tooltip icon-home" data-toggle="tooltip" data-placement="top" data-original-title="Intro"></span></a>
<a href="{% url 'course_material_admin' course.slug %}"><span class="has-tooltip icon-exclamation-sign" data-toggle="tooltip" data-placement="top" data-original-title="Material Didádico"></span></a>
</nav>
<!-- END COURSE-SECTION-NAV -->
</div>
</div>
</div>
Expand Down
59 changes: 59 additions & 0 deletions core/templates/admin/admin-base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
{% block head %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>{{ course }}</title>

<script src="//www.youtube.com/iframe_api"></script>

{% load static %}
{% load compressed %}

{% compressed_css 'common' %}
{% compressed_css 'admin' %}
{% compressed_js 'all' %}

{# TODO: aprender a comprimir estas coisas (fabio) #}
<script type="text/javascript" src="{% static 'js/vendor/pagedown/Markdown.Converter.js' %}" charset="utf-8"></script>
<script type="text/javascript" src="{% static 'js/vendor/pagedown/Markdown.Editor.js' %}" charset="utf-8"></script>
<script type="text/javascript" src="{% static 'js/vendor/pagedown/Markdown.Sanitizer.js' %}" charset="utf-8"></script>
{% endblock %}
</head>
<body id="admin">

<!-- NAVBAR -->
<div id="main-navbar" class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<a class="navbar-brand" href="/">TIM Tec - ADMIN</a>
<ul class="nav navbar-nav pull-right">
<li>
<a href="#">Cursos</a>
</li>
<li>
<a href="#">Usuários</a>
</li>
<li>
<a href="#">Estatísticas</a>
</li>
</ul>
</div>
</div>
<!-- END NAVBAR -->

<!-- WRAPPER -->
<div class="wrapper">
{% block content %}
<h1>missing content block</h1>
{% endblock %}
</div>
<!-- END WRAPPER -->

<!-- FOOTER -->
{% include 'footer.html' %}
<!-- END FOOTER -->

</body>
</html>
2 changes: 1 addition & 1 deletion course_material/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class CourseMaterial(models.Model):
course = models.ForeignKey(Course, verbose_name=_('Course Materials'))
course = models.ForeignKey(Course, related_name='course_material', verbose_name=_('Course Materials'))
text = models.TextField(_('Question'))


Expand Down
8 changes: 8 additions & 0 deletions course_material/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from course_material.models import CourseMaterial
from rest_framework import serializers


class CourseMaterialSerializer(serializers.ModelSerializer):

class Meta:
model = CourseMaterial
2 changes: 1 addition & 1 deletion course_material/static/js/course_material/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


// Declare app level module which depends on filters, and services
angular.module('courseMaterial', ['courseMaterial.services', 'courseMaterial.controllers']);
angular.module('courseMaterial', ['courseMaterial.services', 'courseMaterial.controllers', 'courseMaterial.directives', 'courseMaterial.filters']);
23 changes: 23 additions & 0 deletions course_material/static/js/course_material/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,31 @@ function FileUploadCtrl($scope, $sce, $window) {
var courseId = parseInt($window.question_id, 10);
}

function CourseMaterialEditorCtrl($scope, $sce, $window, CourseMaterial, Course) {
var courseSlug = /[^/]+$/.extract(location.pathname);
$scope.course = Course.get({course_slug: courseSlug}, function (course){
$scope.course_material = CourseMaterial.get({course: $scope.course.id}, function (course_material){
$scope.editor_text = course_material.text;
});
});

// $scope.course_material = CourseMaterial.get({course: $scope.course.id}, function (course_material){
// $scope.editor_text = course_material.text;
// });


$scope.save = function(){
$scope.course_material.text = $scope.editor_text;
$scope.course_material.$update({course: $scope.course.id});
};
$scope.reset = function(){
$scope.editor_text = course_material.text;
};
}

angular.module('courseMaterial.controllers', ['ngCookies']).
controller('FileUploadCtrl', ['$scope', '$sce', '$window', 'FileUploadCtrl', FileUploadCtrl]).
controller('CourseMaterialEditor', ['$scope', '$sce', '$window', 'CourseMaterial','Course', CourseMaterialEditorCtrl]).
run(function ($http, $cookies) {
$http.defaults.headers.common['X-CSRFToken'] = $cookies['csrftoken'];
});
35 changes: 27 additions & 8 deletions course_material/static/js/course_material/directives.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
'use strict';

angular.module('courseMaterial.directives', []).directive('dropZone', function() {
return function(scope, element, attrs) {
element.dropzone({
url: "/upload",
maxFilesize: 100,
paramName: "uploadfile",
angular.module('courseMaterial.directives', []).
directive('dropZone', function() {
return function(scope, element, attrs) {
element.dropzone({
url: "/upload",
maxFilesize: 100,
paramName: "uploadfile",
});
};
}).
directive('markdowneditor', function(){
return {
"restrict": 'A',
"controller": function($scope, $element) {
// $element.find('textarea').attr('id', "wmd-input");
$element.find('.js-button-bar').attr('id', "wmd-button-bar");

var editor = new Markdown.Editor(Markdown.getSanitizingConverter(), '');
editor.run();
},
"link": function(scope, element) {
var read = function read(evt){
scope.editor_text = evt.currentTarget.value;
};
element.find('textarea').on('blur change', read);
}
};
});
};
});
10 changes: 10 additions & 0 deletions course_material/static/js/course_material/filters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

/* Filters */

angular.module('courseMaterial.filters', ["ngSanitize"]).
filter('markdown', ['$window', function($window) {
return function(text) {
return text ? Markdown.getSanitizingConverter().makeHtml(text) : "";
};
}]);
10 changes: 7 additions & 3 deletions course_material/static/js/course_material/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

/* Services */

angular.module('forum.services', ['ngRoute', 'ngResource']).
factory('CourseMaterialService', function($resource){
return $resource('/api/course_material/', {}, {
angular.module('courseMaterial.services', ['ngRoute', 'ngResource']).
factory('CourseMaterial', function($resource){
return $resource('/api/course_material/:course/', {}, {
update: {method: 'PUT'},
});
}).
factory('Course', function($resource){
return $resource('/api/course/:course_slug/',{});
});

1 change: 1 addition & 0 deletions course_material/templates/_course_material_angular.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<script src="{% static 'js/course_material/services.js' %}"></script>
<script src="{% static 'js/course_material/controllers.js' %}"></script>
<script src="{% static 'js/course_material/directives.js' %}"></script>
<script src="{% static 'js/course_material/filters.js' %}"></script>
<script src="{% static 'js/dropzone.js' %}"></script>
111 changes: 111 additions & 0 deletions course_material/templates/course-material-admin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{% extends 'admin/admin-base.html' %}
{% load i18n %}
{% load staticfiles %}
{% load timtec_markdown %}

{% block head %}
{{ block.super }}
{% include "_course_material_angular.html" %}
{% endblock %}

{% block content %}
<script>
window.course_id = {{ course.pk }};</script>
<!-- CONTAINER -->
<div>
<!-- HEADER -->
<header id="main-header" class="container">
<div class="page-header">
<div class="row">
<div class="col-sm-9 col-lg-9">
<h1 class="top editable"><span contenteditable="true" ng-model="course.name"></span></h1>
<h5><span class="icon-addable icon-plus-sign-alt"></span> Adicionar professores ao curso</h5>
</div>
<div class="col-sm-3 col-lg-3 textright">
<!-- COURSE-SECTION-NAV -->
<nav class="course-sections textright">
<a href="{% url 'course_admin' course.slug %}">
<span class="has-tooltip icon-home" data-toggle="tooltip" data-placement="top" data-original-title="Intro"></span>
</a>
<a href="{% url 'course_material_admin' course.slug %}">
<span class="has-tooltip icon-exclamation-sign" data-toggle="tooltip" data-placement="top" data-original-title="Material Didádico"></span>
</a>
</nav>
<!-- END COURSE-SECTION-NAV -->
</div>
</div>
</div>
</header>
<!-- END HEADER -->
<!-- MAIN CONTENT -->
<section id="main-content" class="container">
<div class="row">
<div class="col-sm-9 col-lg-9" ng-app="courseMaterial" ng-controller="CourseMaterialEditorCtrl">
<p class="description">
<span class="description" ng-bind-html="course_material.text|markdown"></span>
</p>
<a data-toggle="modal" href="#course-material-modal">Editar texto</a>
{% verbatim %}
<div class="modal fade" id="course-material-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
&times;
</button>
<h4 class="modal-title">Editar material didático</h4>
</div>
<div class="modal-body">
<div class="text-editor" markdowneditor="true">
<div class="row">
<div class="col-lg-12 js-button-bar"></div>
</div>
<div class="row">
<div class="col-lg-12 form-group">
<textarea id="wmd-input" ng-model="editor_text" class="col-lg-12 form-control" rows="15"></textarea>
</div>
</div>
<div class="js-preview"></div>
</div>
<div class="modal-footer">
<button type="button" ng-click="reset()" class="btn btn-default" data-dismiss="modal">
Cancelar
</button>
<button type="button" ng-click="save()" class="btn btn-primary" data-dismiss="modal">
Save changes
</button>
</div>
</div>
</div>
</div>
</div>
{% endverbatim %}
</div>
<!-- ASIDE -->
<aside class="col-sm-3 col-lg-3">
<form action="{% url 'file_upload' course.slug %}" class="dropzone textcenter" drop-zone id="file-dropzone">
<p>
<strong>Drop</strong> files to upload
<br>
(or click)
</p>
{% csrf_token %}
</form>
<ul class="uploaded-files-list">
<li>
<h5>{% trans "Files" %}</h5>
</li>
{% for file in course_material.files.all %}
<li>
<a href="{{ file.file.url }}">{{ file.file.name }}</a>
</li>
{% endfor %}
</ul>
</aside>
<!-- END ASIDE -->
</div>
</section>
<!-- END MAIN CONTENT-->
</div>
<!-- END CONTAINER -->
{% endblock %}
29 changes: 29 additions & 0 deletions course_material/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
from accounts.utils import LoginRequiredMixin
from core.models import Course
from course_material.forms import FileForm
from course_material.serializers import CourseMaterialSerializer
from course_material.models import CourseMaterial, File
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.views.generic.detail import DetailView
from django.views.generic.edit import FormView
from rest_framework import viewsets
import json


Expand Down Expand Up @@ -47,3 +49,30 @@ def post(self, request, *args, **kwargs):
else:
data = {'error': 400}
return self.render_to_json_response(data, status=400)


class CourseMaterialAdminView(LoginRequiredMixin, DetailView):
model = CourseMaterial
context_object_name = 'course_material'
template_name = 'course-material-admin.html'
slug_field = 'course__slug'

def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(CourseMaterialAdminView, self).get_context_data(**kwargs)
self.course = get_object_or_404(Course, slug=self.kwargs['slug'])
context['course'] = self.course
return context


class CourseMaterialViewSet(LoginRequiredMixin, viewsets.ModelViewSet):
model = CourseMaterial
serializer_class = CourseMaterialSerializer
lookup_field = 'course'

def pre_save(self, obj):
# Get Question vote usign kwarg as questionId
if 'course' in self.kwargs:
obj.course = Course.objects.get(pk=int(self.kwargs['course']))
self.kwargs['course'] = obj.course
return super(CourseMaterialViewSet, self).pre_save(obj)
6 changes: 4 additions & 2 deletions timtec/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from core.views import AdminCourseView, CourseView, CourseViewSet, EnrollCourseView, HomeView, UserCoursesView
from lesson.views import LessonDetailView, LessonViewSet, StudentProgressViewSet, ReceiveAnswerView, UpdateStudentProgressView
from forum.views import CourseForumView, QuestionView, QuestionCreateView, QuestionViewSet, AnswerViewSet, QuestionVoteViewSet, AnswerVoteViewSet
from course_material.views import CourseMaterialView, FileUploadView
from course_material.views import CourseMaterialView, FileUploadView, CourseMaterialAdminView, CourseMaterialViewSet
from rest_framework import routers

router = routers.DefaultRouter(trailing_slash=False)
Expand All @@ -23,6 +23,7 @@
router.register(r'forum_answer', AnswerViewSet)
router.register(r'question_vote', QuestionVoteViewSet)
router.register(r'answer_vote', AnswerVoteViewSet)
router.register(r'course_material', CourseMaterialViewSet)


urlpatterns = patterns(
Expand All @@ -34,7 +35,7 @@
url(r'^django/admin/', include(admin.site.urls)),

# Privileged browsing
url(r'^admin/course/(?P<slug>[-a-zA-Z0-9_]+)$', AdminCourseView.as_view(), name='course_intro'),
url(r'^admin/course/(?P<slug>[-a-zA-Z0-9_]+)$', AdminCourseView.as_view(), name='course_admin'),

# Public browsing
url(r'^my-courses$', UserCoursesView.as_view(), name='user_courses'),
Expand All @@ -57,6 +58,7 @@
# Course Material
url(r'^course_material/file_upload/(?P<slug>[-a-zA-Z0-9_]+)$', FileUploadView.as_view(), name='file_upload'),
url(r'^course_material/(?P<slug>[-a-zA-Z0-9_]+)$', CourseMaterialView.as_view(), name='course_material'),
url(r'^admin/course_material/(?P<slug>[-a-zA-Z0-9_]+)$', CourseMaterialAdminView.as_view(), name='course_material_admin'),

# Authentication
url(r'^login/', CustomLoginView.as_view(), name='timtec_login'),
Expand Down

0 comments on commit ebc9baf

Please sign in to comment.