Skip to content

Commit eb899fd

Browse files
author
Jordan Yoshihara
committed
Merge pull request #1 from jayoshih/fileuploading
Fileuploading
2 parents 4df1374 + e9abb34 commit eb899fd

65 files changed

Lines changed: 1394 additions & 845 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "kolibri"]
2+
path = kolibri
3+
url = https://github.com/learningequality/kolibri.git
4+
[submodule "contentcuration/kolibri"]
5+
path = contentcuration/kolibri
6+
url = https://github.com/learningequality/kolibri.git
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.contrib import admin
22

3-
from contentcuration.models import Exercise, AssessmentItem
3+
from contentcuration.models import Exercise, AssessmentItem, License
44

55
admin.site.register(Exercise)
66
admin.site.register(AssessmentItem)
7+
admin.site.register(License)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.4 on 2016-03-08 00:35
3+
from __future__ import unicode_literals
4+
5+
from django.conf import settings
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
import django.db.models.manager
9+
10+
11+
class Migration(migrations.Migration):
12+
13+
initial = True
14+
15+
dependencies = [
16+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
17+
('content', '0001_initial'),
18+
]
19+
20+
operations = [
21+
migrations.CreateModel(
22+
name='AssessmentItem',
23+
fields=[
24+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
25+
('type', models.CharField(default=b'multiplechoice', max_length=50)),
26+
('question', models.TextField(blank=True)),
27+
('answers', models.TextField(default=b'[]')),
28+
],
29+
),
30+
migrations.CreateModel(
31+
name='Channel',
32+
fields=[
33+
('channelmetadata_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='content.ChannelMetadata')),
34+
],
35+
options={
36+
'verbose_name': 'Channel',
37+
'verbose_name_plural': 'Channels',
38+
},
39+
bases=('content.channelmetadata',),
40+
),
41+
migrations.CreateModel(
42+
name='Exercise',
43+
fields=[
44+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
45+
('title', models.CharField(default='Title', help_text='Title of the content item', max_length=50, verbose_name='title')),
46+
('description', models.TextField(default='Description', help_text='Brief description of what this content item is', max_length=200, verbose_name='description')),
47+
],
48+
),
49+
migrations.CreateModel(
50+
name='Node',
51+
fields=[
52+
('contentmetadata_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='content.ContentMetadata')),
53+
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
54+
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
55+
('published', models.BooleanField(default=False, help_text='If published, students can access this item', verbose_name='Published')),
56+
('sort_order', models.FloatField(default=0, help_text='Ascending, lowest number shown first', max_length=50, verbose_name='sort order')),
57+
('license_owner', models.CharField(blank=True, help_text='Organization of person who holds the essential rights', max_length=255, null=True)),
58+
],
59+
options={
60+
'verbose_name': 'Topic',
61+
'verbose_name_plural': 'Topics',
62+
},
63+
bases=('content.contentmetadata',),
64+
managers=[
65+
('_default_manager', django.db.models.manager.Manager()),
66+
],
67+
),
68+
migrations.CreateModel(
69+
name='TopicTree',
70+
fields=[
71+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
72+
('name', models.CharField(help_text='Displayed to the user', max_length=255, verbose_name='topic tree name')),
73+
('is_published', models.BooleanField(default=False, help_text='If published, students can access this channel', verbose_name='Published')),
74+
('channel', models.ForeignKey(help_text='For different versions of the tree in the same channel (trash, edit, workspace)', null=True, on_delete=django.db.models.deletion.CASCADE, to='contentcuration.Channel', verbose_name='channel')),
75+
('root_node', models.ForeignKey(help_text='The starting point for the tree, the title of it is the title shown in the menu', null=True, on_delete=django.db.models.deletion.CASCADE, to='contentcuration.Node', verbose_name='root node')),
76+
],
77+
options={
78+
'verbose_name': 'Topic tree',
79+
'verbose_name_plural': 'Topic trees',
80+
},
81+
),
82+
migrations.AddField(
83+
model_name='channel',
84+
name='clipboard',
85+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='clipboard', to='contentcuration.TopicTree'),
86+
),
87+
migrations.AddField(
88+
model_name='channel',
89+
name='deleted',
90+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='deleted', to='contentcuration.TopicTree'),
91+
),
92+
migrations.AddField(
93+
model_name='channel',
94+
name='draft',
95+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='draft', to='contentcuration.TopicTree'),
96+
),
97+
migrations.AddField(
98+
model_name='channel',
99+
name='editors',
100+
field=models.ManyToManyField(help_text='Users with edit rights', to=settings.AUTH_USER_MODEL, verbose_name='editors'),
101+
),
102+
migrations.AddField(
103+
model_name='channel',
104+
name='published',
105+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='published', to='contentcuration.TopicTree'),
106+
),
107+
migrations.AddField(
108+
model_name='assessmentitem',
109+
name='exercise',
110+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='all_assessment_items', to='contentcuration.Exercise'),
111+
),
112+
]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.4 on 2016-03-08 01:02
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('contentcuration', '0001_initial'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='ContentLicense',
17+
fields=[
18+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('name', models.CharField(default=b'', help_text="Name of license, e.g. 'Creative Commons Share-Alike 2.0'", max_length=255, verbose_name='name')),
20+
('exists', models.BooleanField(default=False, help_text='Tells whether or not a content item is licensed to share', verbose_name='license exists')),
21+
],
22+
),
23+
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.4 on 2016-04-04 19:08
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
('content', '0001_initial'),
13+
('contentcuration', '0002_contentlicense'),
14+
]
15+
16+
operations = [
17+
migrations.RemoveField(
18+
model_name='contentlicense',
19+
name='id',
20+
),
21+
migrations.RemoveField(
22+
model_name='contentlicense',
23+
name='name',
24+
),
25+
migrations.AddField(
26+
model_name='contentlicense',
27+
name='license_ptr',
28+
field=models.OneToOneField(auto_created=True, default=1, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='content.License'),
29+
preserve_default=False,
30+
),
31+
]

contentcuration/contentcuration/migrations/__init__.py

Whitespace-only changes.

contentcuration/contentcuration/models.py

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
11
from django.db import models
22
from mptt.models import MPTTModel, TreeForeignKey
33
from django.utils.translation import ugettext as _
4+
from kolibri.content.models import *
45

5-
6-
class Channel(models.Model):
6+
class Channel(ChannelMetadata):
77
""" Permissions come from association with organizations """
8-
name = models.CharField(
9-
max_length= 100,
10-
verbose_name=_("channel name"),
11-
)
12-
description = models.TextField(
13-
max_length = 300,
14-
verbose_name=_("channel description"),
15-
help_text=_("Description of what a channel contains"),
16-
)
17-
author = models.CharField(
18-
max_length=100,
19-
verbose_name=_("channel author"),
20-
help_text=_("Channel author can be a person or an organization"),
21-
)
228
editors = models.ManyToManyField(
239
'auth.User',
2410
verbose_name=_("editors"),
@@ -34,7 +20,6 @@ class Meta:
3420
verbose_name = _("Channel")
3521
verbose_name_plural = _("Channels")
3622

37-
3823
class TopicTree(models.Model):
3924
"""Base model for all channels"""
4025

@@ -69,48 +54,22 @@ class Meta:
6954
verbose_name_plural = _("Topic trees")
7055

7156

72-
class Node(MPTTModel):
57+
class Node(ContentMetadata):
7358
"""
7459
By default, all nodes have a title and can be used as a topic.
7560
"""
7661

7762
created = models.DateTimeField(auto_now_add=True, verbose_name=_("created"))
7863
modified = models.DateTimeField(auto_now=True, verbose_name=_("modified"))
7964

80-
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
81-
82-
title = models.CharField(
83-
max_length=50,
84-
verbose_name=_("title"),
85-
default=_("Title"),
86-
help_text=_("Node title"),
87-
)
88-
89-
description = models.TextField(
90-
max_length=200,
91-
verbose_name=_("description"),
92-
default=_("Description"),
93-
help_text=_("Brief description of what is contained in this folder"),
94-
)
95-
9665
published = models.BooleanField(
9766
default=False,
9867
verbose_name=_("Published"),
9968
help_text=_("If published, students can access this item"),
10069
)
10170

102-
deleted = models.BooleanField(
103-
default=False,
104-
verbose_name=_("Deleted"),
105-
help_text=_(
106-
"Indicates that the node has been deleted, and should only "
107-
"be retrievable through the admin backend"
108-
),
109-
)
110-
11171
sort_order = models.FloatField(
11272
max_length=50,
113-
#unique=True,
11473
default=0,
11574
verbose_name=_("sort order"),
11675
help_text=_("Ascending, lowest number shown first"),
@@ -123,20 +82,6 @@ class Node(MPTTModel):
12382
help_text=_("Organization of person who holds the essential rights"),
12483
)
12584

126-
license = models.ForeignKey(
127-
'ContentLicense',
128-
null=True,
129-
verbose_name=_("license"),
130-
help_text=_("License under which the work is distributed"),
131-
)
132-
133-
kind = models.CharField(
134-
max_length=50,
135-
verbose_name=_("kind"),
136-
help_text=_("Type of node (topic, video, exercise, etc.)"),
137-
default="Topic"
138-
)
139-
14085
@property
14186
def has_draft(self):
14287
return self.draft_set.all().exists()
@@ -157,23 +102,7 @@ class Meta:
157102
verbose_name = _("Topic")
158103
verbose_name_plural = _("Topics")
159104
# Do not allow two nodes with the same name on the same level
160-
unique_together = ('parent', 'title')
161-
162-
163-
164-
class ContentLicense(models.Model):
165-
name = models.CharField(
166-
max_length=255,
167-
default=(""),
168-
verbose_name=_("name"),
169-
help_text=_("Name of license, e.g. 'Creative Commons Share-Alike 2.0'"),
170-
)
171-
exists = models.BooleanField(
172-
default=False,
173-
verbose_name=_("license exists"),
174-
help_text=_("Tells whether or not a content item is licensed to share"),
175-
)
176-
105+
#unique_together = ('parent', 'title')
177106

178107
# If we decide to subclass Content:
179108
#
@@ -214,7 +143,12 @@ class ContentLicense(models.Model):
214143
# """
215144
# Model for Exercise data
216145
# """
217-
146+
class ContentLicense(License):
147+
exists = models.BooleanField(
148+
default=False,
149+
verbose_name=_("license exists"),
150+
help_text=_("Tells whether or not a content item is licensed to share"),
151+
)
218152

219153
class Exercise(models.Model):
220154

contentcuration/contentcuration/serializers.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
class LicenseSerializer(serializers.ModelSerializer):
66
class Meta:
77
model = ContentLicense
8-
fields = ('name', 'id')
8+
fields = ('license_name', 'exists', 'id')
99

1010
class ChannelSerializer(serializers.ModelSerializer):
1111
class Meta:
1212
model = Channel
13-
fields = ('name', 'description', 'editors', 'id', 'draft', 'clipboard', 'deleted', 'published')
13+
fields = ('name', 'description', 'editors', 'id', 'draft', 'clipboard', 'deleted', 'published','channel_id')
1414

1515
class TopicTreeSerializer(serializers.ModelSerializer):
1616
class Meta:
@@ -20,16 +20,29 @@ class Meta:
2020
class NodeSerializer(BulkSerializerMixin, serializers.ModelSerializer):
2121
class Meta:
2222
model = Node
23-
fields = ('title', 'published', 'deleted', 'id', 'description', 'published',
24-
'sort_order', 'license_owner', 'license', 'kind', 'children', 'parent')
23+
fields = ('title', 'published', 'total_file_size', 'id', 'description', 'published',
24+
'sort_order', 'license_owner', 'license', 'kind', 'children', 'parent', 'content_id')
2525

26+
class FileSerializer(serializers.ModelSerializer):
27+
class Meta:
28+
model = File
29+
fields = ('checksum', 'extension', 'file_size', 'content_copy', 'id', 'available', 'format')
30+
31+
class FormatSerializer(serializers.ModelSerializer):
32+
class Meta:
33+
model = Format
34+
fields = ('format_size', 'quality', 'contentmetadata', 'available', 'mimetype', 'id')
35+
36+
class MimeTypeSerializer(serializers.ModelSerializer):
37+
class Meta:
38+
model = MimeType
39+
fields = ('readable_name', 'machine_name', 'id')
2640

2741
class ExerciseSerializer(serializers.ModelSerializer):
2842
class Meta:
2943
model = Exercise
3044
fields = ('title', 'description', 'id')
3145

32-
3346
class AssessmentItemSerializer(BulkSerializerMixin, serializers.ModelSerializer):
3447
exercise = serializers.PrimaryKeyRelatedField(queryset=Exercise.objects.all())
3548

contentcuration/contentcuration/settings.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
'django.contrib.staticfiles',
4242
'rest_framework',
4343
'django_js_reverse',
44+
'kolibri.content',
4445
)
4546

4647
MIDDLEWARE_CLASSES = (
@@ -113,6 +114,8 @@
113114

114115
STATIC_URL = '/static/'
115116

116-
DEFAULT_FILE_STORAGE = 'django_hashedfilenamestorage.storage.HashedFilenameFileSystemStorage'
117+
DEFAULT_FILE_STORAGE = 'kolibri.content.models.ContentCopyStorage'
117118

118119
LOGIN_REDIRECT_URL = '/exercises/'
120+
121+
CONTENT_COPY_DIR = BASE_DIR
82.2 KB
Loading

0 commit comments

Comments
 (0)